C++11: Compile Time Calculation of Array

c++, c++11, constexpr, templates

Solution

There is a pure C++11 (no boost, no macros too) solution to this problem. Using the same trick as this answer we can build a sequence of numbers and unpack them to call `f` to construct a `std::array`:

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

(Tested with g++ 4.7)

You could skip `std::array` entirely with a bit more work, but I think in this instance it's cleaner and simpler to just use `std::array`.

You can also do this recursively:

#include <array>
#include <functional>
#include <algorithm>
#include <iterator>
#include <iostream>

constexpr int f(int n) {
  return n;
}

template <int N, int ...Vals>
constexpr
typename std::enable_if<N==sizeof...(Vals),std::array<int, N>>::type
make() {
  return std::array<int,N>{{Vals...}};
}

template <int N, int ...Vals>
constexpr
typename std::enable_if<N!=sizeof...(Vals), std::array<int,N>>::type 
make() {
  return make<N, Vals..., f(sizeof...(Vals))>();  
}

int main() {
  const auto arr = make<10>();
  std::copy(begin(arr), end(arr), std::ostream_iterator<int>(std::cout, "\n"));
}

Which is arguably simpler.

Problem

Suppose I have some constexpr function f: ``` constexpr int f(int x) { ... } ``` And I have some const int N known at compile time: Either ``` #define N ...; ``` or ``` const int N = ...; ``` as needed by your answer. I want to have an int array X: ``` int X[N] = { f(0), f(1), f(2), ..., f(N-1) } ``` such that the function is evaluated at compile time, and the entries in X are calculated by the compiler and the results are placed in the static area of my application image exactly as if I had used integer literals in my X initializer list. Is there some way I can write this? (For example with templates or macros and so on) Best I have: (Thanks to Flexo) ``` #include <iostream> #include <array> using namespace std; constexpr int N = 10; constexpr int f(int x) { return x*2; } typedef array<int, N> A; template<int... i> constexpr A fs() { return A{{ f(i)... }}; } template<int...> struct S; template<int... i> struct S<0,i...> { static constexpr A gs() { return fs<0,i...>(); } }; template<int i, int... j> struct S<i,j...> { static constexpr A gs() { return S<i-1,i,j...>::gs(); } }; constexpr auto X = S<N-1>::gs(); int main() { cout << X[3] << endl; } ```

Original source

Related problems