关于元编程的几个问题?
Several questions about metaprogramming?
希望得到一个编译时数组,所以来this answer。以下是答案中的代码:
#include <array>
#include <algorithm>
#include <iterator>
#include <iostream>
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;
};
constexpr int f(int n) {
return n;
}
template <int N>
class array_thinger {
typedef typename gens<N>::type list;
template <int ...S>
static constexpr std::array<int,N> make_arr(seq<S...>) {
return std::array<int,N>{{f(S)...}};
}
public:
static constexpr std::array<int,N> arr = make_arr(list());
};
template <int N>
constexpr std::array<int,N> array_thinger<N>::arr;
int main() {
std::copy(begin(array_thinger<10>::arr), end(array_thinger<10>::arr),
std::ostream_iterator<int>(std::cout, "\n"));
}
但是我是元编程的新手,所以这里有两个问题:
struct gens : gens<N-1, N-1, S...>
的语法是什么?在 c++0x 中似乎是 Delegating constructors
,但我不确定。
struct seq
和typedef seq<S...> type
的用法是什么?啊,我对模板也没有很好的掌握。
您拥有的是一个以递归方式调用自身的模板。
如果你写:
gens<3>::type
它使用您的模板
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
因此N变为3,S中的参数为none。模板结构本身派生自 gens<N-1, N-1, S...>
,然后在此处变为 gens<2,2>
。这将再次调用(递归!)本身。
所以用 N=2 调用 gens 模板,S 是一个列表,其中一个元素包含一个 int : 2。再次调用 gens
,现在用 `gens<1,1,2> .
重复直到 N 变为 0。现在,由于氏族的特化:
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
将调用此专业化。所以这里我们得到gens<0,0,1,2>。所以 N 是 0,S 是 0,1,2 的列表。现在模板生成类型 type
。类型现在是 seq<0,1,2>.
由于 gens 从自身递归派生,您可以从该继承序列中获取类型,因为 0 的特化是结构的根。
所以你可以这样写:
gens<3>::type
即:seq<0,1,2>
希望得到一个编译时数组,所以来this answer。以下是答案中的代码:
#include <array>
#include <algorithm>
#include <iterator>
#include <iostream>
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;
};
constexpr int f(int n) {
return n;
}
template <int N>
class array_thinger {
typedef typename gens<N>::type list;
template <int ...S>
static constexpr std::array<int,N> make_arr(seq<S...>) {
return std::array<int,N>{{f(S)...}};
}
public:
static constexpr std::array<int,N> arr = make_arr(list());
};
template <int N>
constexpr std::array<int,N> array_thinger<N>::arr;
int main() {
std::copy(begin(array_thinger<10>::arr), end(array_thinger<10>::arr),
std::ostream_iterator<int>(std::cout, "\n"));
}
但是我是元编程的新手,所以这里有两个问题:
struct gens : gens<N-1, N-1, S...>
的语法是什么?在 c++0x 中似乎是Delegating constructors
,但我不确定。struct seq
和typedef seq<S...> type
的用法是什么?啊,我对模板也没有很好的掌握。
您拥有的是一个以递归方式调用自身的模板。
如果你写:
gens<3>::type
它使用您的模板
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
因此N变为3,S中的参数为none。模板结构本身派生自 gens<N-1, N-1, S...>
,然后在此处变为 gens<2,2>
。这将再次调用(递归!)本身。
所以用 N=2 调用 gens 模板,S 是一个列表,其中一个元素包含一个 int : 2。再次调用 gens
,现在用 `gens<1,1,2> .
重复直到 N 变为 0。现在,由于氏族的特化:
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
将调用此专业化。所以这里我们得到gens<0,0,1,2>。所以 N 是 0,S 是 0,1,2 的列表。现在模板生成类型 type
。类型现在是 seq<0,1,2>.
由于 gens 从自身递归派生,您可以从该继承序列中获取类型,因为 0 的特化是结构的根。
所以你可以这样写:
gens<3>::type
即:seq<0,1,2>