我如何(如果可能的话)如何使用c ++ 11可变参数编程vector
在函数体中定义一系列“ ”(或换句话说,一个N
由-递减N
到0的-维数组序列),就像下面的变量一样?
vector<vector<vector<int>>> v<3>;
vector<vector<int>> v<2>;
vector<int> v<1>;
int v<0>;
我想象的是这样的:
#include <iostream>
#include <vector>
using namespace std;
template<int ...> struct seq {};
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};
template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
template<int ...S>
void f(seq<S...>) {
//how do I write definitions of v<N> here?
vector<vector<...(N layers)<vector<int> ...> v<N>; //??how-to, not valid c++
vector<vector<...(N -1 layers)<vector<int> ...> v<N-1>;//??how-to, not valid c++
//...
vector<int> v<1>; //??how-to, not valid c++
int v<0>; //??how-to, not valid c++
//...
}
int main() {
f(typename gens<3>);
return 0;
}
另外,这在c ++ 14中会更容易吗?
谢谢,
- 编辑 -
为了明确起见,我所说的“向量塔”最好用一个N元组(v_1,v_2,...,v_N)描述,其中N是一个不可或缺的模板参数。v_1是向量,v_2是向量>,依此类推。
-编辑2--
到目前为止,quantdev和R的答案已成功解决了为任何固定N(例如3)定义N元组的问题,但无法为未指定的N生成元组N
。除了答案中的功能外,我还需要一个可以像gen_tower<N>
return一样使用的功能tuple(v1,v2,...,vN)
。
考虑使用可变参数编程来计算阶乘的示例。除了能够手动写出任何特定表达式的能力之外,我还需要一个函数来计算factorial<N>()
任何因子。(这就是为什么我询问可变参数编程以及是否会使它变得更容易的原因。)N
<1*2*3>
c++14
聚苯乙烯
纯粹出于个人利益,我希望此序列希望实现一个通用功能,该功能可以从文件读取N维数组。我尚不清楚确切的方法,但是我认为在第一步中,我应该能够定义finalN
维数组,以及from至to的中间k
维数组。我可以读取2维数组和3维数组。但是能够读取任何尺寸的数组将是很好的。k
N-1
1
不需要variadics,递归typedef
就足以在编译时生成这些类型。
如何实施?
1)提供一个带有2个参数的模板:矢量元素类型(T
)和结构的所需尺寸(size_t N
)。声明一个typedef type
:它将基于type
使用depth实例化的模板的声明N-1
,因此是递归的。
template<typename T, size_t N>
struct VectorGenerator
{
typedef std::vector< typename VectorGenerator<T, N-1>::type > type;
};
2)提供用于终止递归的终止条件,这里是维度为0的模板的特殊化,声明了common的类型std::vector<T>
。
template<typename T>
struct VectorGenerator<T, 0>
{
typedef std::vector<T> type;
};
如何使用它 ?
现在我们可以声明一个v
类型的向量VectorGenerator<T, N>::type
:
VectorGenerator<double, 4>::type v; // v as a depth of 4 and handle double
但这不是很可读或不方便,而且很冗长。让我们为我们的类型引入新名称。
这是模板别名的完美案例,使用(C ++ 11)using
关键字作为别名。我们有2种不同的别名方式:
1)为特定的尺寸和类型声明别名,在这里我们将其称为N=3
和的V3 T=double
:
using V3 = VectorGenerator<double, 3>::type; // Alias
V3 v; // Use the alias
或者,
2)为特定类型声明模板别名,将维度保留为模板参数:
template <size_t N>
using V = typename VectorGenerator<double, N>::type; // Alias
V<3> v; // Use the Alias
最终代码示例:
template<typename T, size_t N>
struct VectorGenerator
{
typedef std::vector< typename VectorGenerator<T, N-1>::type > type;
};
template<typename T>
struct VectorGenerator<T, 0>
{
typedef std::vector<T> type;
};
// Alias for V3, V2 ... usage
using V3 = VectorGenerator<double, 3>::type;
using V2 = VectorGenerator<double, 2>::type;
// Alias for V <k> usage
template <size_t N>
using V = typename VectorGenerator<double, N>::type;
int main() {
V<3> v3;
V<2> v2;
v3.push_back(v2);
return 0;
}
注意事项:
tuple
现在很容易声明带有多个不同维的向量:例子:
auto tower = std::tuple<V<1>, V<2>, V<3>>(v1, v2, v3);
对于生成多个“塔”的通用元组,@ mpark提供了一个有效的C ++ 14解决方案,在这里将其调整为我的代码示例:
template <typename T>
struct identity { using type = T; };
// Generate a tuple of towers by mapping index_sequence over gen_tower.
template <typename T, std::size_t... Is>
std::tuple<VectorGenerator<T, Is>...> gen_towers_impl(std::integer_sequence<Is...>);
// Make an index_sequence for N and use gen_towers_impl.
template <typename T, std::size_t N>
struct gen_towers
: identity<decltype(gen_towers_impl<T>(std::make_index_sequence<N>()))> {};
// Convenience type aliases
template <typename T, std::size_t N>
using gen_towers_t = typename gen_towers<T, N>::type;
您将需要对其-std=c++1y
进行编译(包括include<utility>
和<tuple>
headers)
在这里查看工作示例。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句