关于元编程的几个问题?

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"));
}

但是我是元编程的新手,所以这里有两个问题:

  1. struct gens : gens<N-1, N-1, S...> 的语法是什么?在 c++0x 中似乎是 Delegating constructors,但我不确定。
  2. struct seqtypedef 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>