Li Chen
Li Chen

Reputation: 5280

Several questions about metaprogramming?

I hope to get a compile-time array, so come to this answer. Below is codes from the 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"));
}

But I am a newbie for metaprogramming, so here are two questions:

  1. what is the syntax of struct gens : gens<N-1, N-1, S...>? It seems like Delegating constructors in c++0x, but I'm not sure.
  2. what is the usage of struct seq and typedef seq<S...> type? Ahh, I also have no good command of template.

Upvotes: 0

Views: 64

Answers (1)

Klaus
Klaus

Reputation: 25663

What you have is a template which calls it self in recursive way.

If you write:

gens<3>::type

it uses your template

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

For that N becomes 3 and the parameters in S are none. The template struct itself derives from gens<N-1, N-1, S...> which then becomes here gens<2,2>. This will again call ( recursive! ) itself.

So the gens template is called with N=2 and S is a list with one element which contains one int : 2. That again calls gens, now with `gens<1,1,2>.

That repeat until N becomes 0. Now, because of the specialization of gens:

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

this specialization will be called. So here we get gens<0,0,1,2>. So N is 0 and S is a list of 0,1,2. Now the template generate the type type. Type is now seq< 0,1,2>.

As gens derives recursive from itself, you can get type from that sequence of inheritance, because the specialization for 0 is the root of the struct.

So you can write:

 gens<3>::type

which is: seq<0,1,2>

Upvotes: 1

Related Questions