在C++中生成任意嵌套的向量
Generate Arbitrarily Nested Vectors in C++
我正在尝试编写一个函数,以便生成任意嵌套的向量并使用C++中的给定特定值进行初始化。例如,auto test_vector = n_dim_vector_generator<2, long double>(static_cast<long double>(1), 1);
应创建一个类型为std::vector<std::vector<long double>>
的"test_vector"对象。 此test_vector的内容应与以下代码相同。
std::vector<long double> vector1;
vector1.push_back(1);
std::vector<std::vector<long double>> test_vector;
test_vector.push_back(vector1);
n_dim_vector_generator函数的更复杂的用法:
auto test_vector2 = n_dim_vector_generator<15, long double>(static_cast<long double>(2), 3);
在这种情况下,参数static_cast<long double>(2)
作为向量中的数据,3
数作为推送时间。因此,此test_vector2的内容应与以下代码相同。
std::vector<long double> vector1;
vector1.push_back(static_cast<long double>(2));
vector1.push_back(static_cast<long double>(2));
vector1.push_back(static_cast<long double>(2));
std::vector<std::vector<long double>> vector2;
vector2.push_back(vector1);
vector2.push_back(vector1);
vector2.push_back(vector1);
std::vector<std::vector<std::vector<long double>>> vector3;
vector3.push_back(vector2);
vector3.push_back(vector2);
vector3.push_back(vector2);
//...Totally repeat 15 times in order to create test_vector2
std::vector<...std::vector<long double>> test_vector2;
test_vector2.push_back(vector14);
test_vector2.push_back(vector14);
test_vector2.push_back(vector14);
实现n_dim_vector_generator函数的详细信息如下。
#include <iostream>
#include <vector>
template <typename T, std::size_t N>
struct n_dim_vector_type;
template <typename T>
struct n_dim_vector_type<T, 0> {
using type = T;
};
template <typename T, std::size_t N>
struct n_dim_vector_type {
using type = std::vector<typename n_dim_vector_type<T, N - 1>::type>;
};
template<std::size_t N, typename T>
typename n_dim_vector_type<T,N>::type n_dim_vector_generator(T t, unsigned int);
template <std::size_t N, typename T>
typename n_dim_vector_type<T, N>::type n_dim_vector_generator<N, T>(T input_data, unsigned int push_back_times) {
if (N == 0)
{
return std::move(input_data);
}
typename n_dim_vector_type<T, N>::type return_data;
for (size_t loop_number = 0; loop_number < push_back_times; loop_number++)
{
return_data.push_back(n_dim_vector_generator<N - 1, T>(input_data, push_back_times));
}
return return_data;
}
结果,我得到了一个错误,'return': cannot convert from 'long double' to 'std::vector<std::vector<long double,std::allocator<long double>>,std::allocator<std::vector<long double,std::allocator<long double>>>>'
我知道它是由if (N == 0)
块引起的,该块是递归结构的终止条件。但是,如果我尝试将终止条件编辑为单独的形式。
template <typename T>
inline T n_dim_vector_generator<0, T>(T input_data, unsigned int push_back_times) {
return std::move(input_data);
}
template <std::size_t N, typename T>
typename n_dim_vector_type<T, N>::type n_dim_vector_generator<N, T>(T input_data, unsigned int push_back_times) {
typename n_dim_vector_type<T, N>::type return_data;
for (size_t loop_number = 0; loop_number < push_back_times; loop_number++)
{
return_data.push_back(n_dim_vector_generator<N - 1, T>(input_data, push_back_times));
}
return return_data;
}
错误'n_dim_vector_generator': illegal use of explicit template arguments
发生。这个问题有更好的解决方案吗?
开发环境位于 Windows 10 1909 中,Microsoft Visual Studio Enterprise 2019 版本 16.4.3
要实现以下各项的特定映射:
auto test_vector = n_dim_vector_generator<2, long double>(2, 3)
对于填充 2 的 3x3 向量,如果您利用此vector
构造函数,您的模板可能会更简单一些:
std::vector<std::vector<T>>(COUNT, std::vector<T>(...))
由于vector
是可复制的,这将用不同的矢量副本填充 COUNT 插槽。 所以...
template <size_t N, typename T>
struct n_dim_vector_generator {
using type = std::vector<typename n_dim_vector_generator<N-1, T>::type>;
type operator()(T value, size_t size) {
return type(size, n_dim_vector_generator<N-1, T>{}(value, size));
}
};
template <typename T>
struct n_dim_vector_generator<0, T> {
using type = T;
type operator()(T value, size_t size) {
return value;
}
};
用法:
auto test_vector = n_dim_vector_generator<2, long double>{}(2, 3);
演示:https://godbolt.org/z/eiDAUG
为了记录,为了解决注释中的一些问题,C++有一个惯用的、可初始化的、连续的内存类,相当于一个多维 C 数组:一个嵌套std::array
:
std::array<std::array<long double, COLUMNS>, ROWS> test_array = { /*...*/ };
for (auto& row : test_array)
for (auto cell : row)
std::cout << cell << std::endl;
如果要减少样板以声明一个,则可以为此使用结构:
template <typename T, size_t... N>
struct multi_array;
template <typename T, size_t NFirst, size_t... N>
struct multi_array<T, NFirst, N...> {
using type = std::array<typename multi_array<T, N...>::type, NFirst>;
};
template <typename T, size_t NLast>
struct multi_array<T, NLast> {
using type = std::array<T, NLast>;
};
template <typename T, size_t... N>
using multi_array_t = typename multi_array<T, N...>::type;
然后使用:
multi_array_t<long double, ROWS, COLUMNS> test_array = { /*...*/ };
for (auto& row : test_array)
for (auto cell : row)
std::cout << cell << std::endl;
这是在堆栈上分配的,就像 C 数组一样。当然,这会占用您的堆栈空间以进行大数组。但是,您可以在std::unique_ptr
周围创建一个装饰器范围,以使指向一个的指针更容易访问:
template <typename T, size_t... N>
struct dynamic_multi_array : std::unique_ptr<multi_array_t<T, N...>> {
using std::unique_ptr<multi_array_t<T, N...>>::unique_ptr;
constexpr typename multi_array_t<T, N...>::value_type& operator [](size_t index) { return (**this)[index]; }
constexpr const typename multi_array_t<T, N...>::value_type& operator [](size_t index) const { return (**this)[index]; }
constexpr typename multi_array_t<T, N...>::iterator begin() { return (**this).begin(); }
constexpr typename multi_array_t<T, N...>::iterator end() { return (**this).end(); }
constexpr typename multi_array_t<T, N...>::const_iterator begin() const { return (**this).begin(); }
constexpr typename multi_array_t<T, N...>::const_iterator end() const { return (**this).end(); }
constexpr typename multi_array_t<T, N...>::const_iterator cbegin() const { return (**this).cbegin(); }
constexpr typename multi_array_t<T, N...>::const_iterator cend() const { return (**this).cend(); }
constexpr typename multi_array_t<T, N...>::size_type size() const { return (**this).size(); }
constexpr bool empty() const { return (**this).empty(); }
constexpr typename multi_array_t<T, N...>::value_type* data() { return (**this).data(); }
constexpr const typename multi_array_t<T, N...>::value_type* data() const { return (**this).data(); }
};
(如果您将这些方法与nullptr
一起使用,请让买家当心(
然后,您仍然可以用大括号初始化new
表达式,并将其用作容器:
dynamic_multi_array<long double, ROWS, COLUMNS> test_array {
new multi_array_t<long double, ROWS, COLUMNS> { /* ... */ }
};
for (auto& row : test_array)
for (auto cell : row)
std::cout << cell << std::endl;
演示:https://godbolt.org/z/lUwVE_
- 选择和修改嵌套向量中的条目的最佳实践
- 嵌套向量的缺点是什么?
- 删除嵌套向量中具有remove_if的元素
- 在循环访问嵌套向量时删除元素
- C++:清除嵌套向量会导致奇怪的结果
- 类字符串和嵌套向量C
- 如何在C 中打印出嵌套向量的内容
- 使用嵌套向量动态分配方阵
- 在嵌套向量C 中获取特定元素
- C++崩溃:push_back嵌套向量
- 初始化嵌套向量的大小
- 针对大型嵌套向量的高效内存分配
- 初始化具有预留容量的嵌套向量的子向量
- 如何获取嵌套向量的尺寸(嵌套性)(不是大小)
- 如何创建一个完全动态的嵌套向量
- 是在连续空间中分配的嵌套向量
- 如何在嵌套向量中获取元素类型
- 使用具有嵌套向量的迭代器的意外行为
- 2 个对象的 STL 嵌套向量
- 嵌套c++向量的重新定位