0

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.
Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • 1
    **1.** It's inheritance. `gens` is derived from `gens` **2.** It's a plain old `typedef`. The name `type` is declared as an alias for the type `seq` – Igor Tandetnik Nov 22 '17 at 05:36
  • The example you saw is a more complicated implementation of an integer sequence, which is recursion with divide and conquer. It is used to avoid large instantiation depths. – Passer By Nov 22 '17 at 05:48
  • For a simpler example, see [this](https://stackoverflow.com/a/27125297/4832499) – Passer By Nov 22 '17 at 05:53

1 Answers1

1

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>

Klaus
  • 24,205
  • 7
  • 58
  • 113