关于元编程的几个问题?

时间:2017-11-22 05:29:19

标签: c++ templates 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的用法是什么?啊,我也没有很好的模板命令。

1 个答案:

答案 0 :(得分:1)

你所拥有的是一个以递归方式自我调用的模板。

如果你写:

gens<3>::type

它使用您的模板

template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };

因为N变为3而S中的参数为无。模板结构本身派生自gens<N-1, N-1, S...>,然后变为gens<2,2>。这将再次调用(递归!)本身。

因此,使用N = 2调用gens模板,S是一个包含一个int的元素的列表:2。再次调用gens,现在使用`gens&lt; 1,1,2&gt;。< / p>

重复,直到N变为0.现在,由于gens的专业化:

template<int ...S>
    struct gens<0, S...> {
    typedef seq<S...> type;
};

将调用此专业化。所以这里我们得到gens&lt; 0,0,1,2&gt;。所以N是0而S是0,1,2的列表。现在模板生成类型type。类型现在是seq&lt; 0,1,2&GT;

当gens从自身递归递归时,你可以从该继承序列中获取类型,因为0的特化是结构的根。

所以你可以写:

 gens<3>::type

是:seq<0,1,2>