C++ 11:编译数组的时间计算

And*_*zos 40 c++ templates constexpr c++11

假设我有一些constexpr函数f:

constexpr int f(int x) { ... }
Run Code Online (Sandbox Code Playgroud)

我在编译时知道一些const int N:

#define N ...;
Run Code Online (Sandbox Code Playgroud)

要么

const int N = ...;
Run Code Online (Sandbox Code Playgroud)

根据你的答案需要.

我想要一个int数组X:

int X[N] = { f(0), f(1), f(2), ..., f(N-1) }
Run Code Online (Sandbox Code Playgroud)

这样在编译时评估函数,X中的条目由编译器计算,结果放在我的应用程序映像的静态区域,就像我在X初始化列表中使用整数文字一样.

有什么方法可以写这个吗?(例如,使用模板或宏等)

我有最好的:(感谢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;
}
Run Code Online (Sandbox Code Playgroud)

Fle*_*exo 30

这个问题有一个纯C++ 11(没有提升,也没有宏)解决方案.使用与此答案相同的技巧,我们可以构建一个数字序列并解压缩它们以调用f构造一个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"));
}
Run Code Online (Sandbox Code Playgroud)

(用g ++ 4.7测试)

您可以std::array完全跳过更多的工作,但我认为在这种情况下使用它更简洁std::array.

您也可以递归执行此操作:

#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"));
}
Run Code Online (Sandbox Code Playgroud)

这可以说更简单.

  • 在这种情况下需要全括号(`{{...}}`)*. (3认同)