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

2023-03-10C/C++开发问题
1

本文介绍了C++11:数组的编译时间计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

假设我有一些 constexpr 函数 f:

Suppose I have some constexpr function f:

constexpr int f(int x) { ... }

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

And I have some const int N known at compile time:

要么

#define N ...;

const int N = ...;

根据您的回答的需要.

我想要一个 int 数组 X:

I want to have an int array X:

int X[N] = { f(0), f(1), f(2), ..., f(N-1) }

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

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)

我最好的:(感谢 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;
}

推荐答案

有一个纯 C++11(没有 boost,也没有宏)解决这个问题.使用与 this answer 相同的技巧,我们可以构建一个数字序列并将它们解包以调用 f 构造一个 std::array:

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

(使用 g++ 4.7 测试)

(Tested with g++ 4.7)

你可以完全跳过 std::array 多做一点工作,但我认为在这种情况下,只使用 std::array 更干净、更简单.

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

可以说更简单.

这篇关于C++11:数组的编译时间计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

The End

相关推荐

无法访问 C++ std::set 中对象的非常量成员函数
Unable to access non-const member functions of objects in C++ std::set(无法访问 C++ std::set 中对象的非常量成员函数)...
2024-08-14 C/C++开发问题
17

从 lambda 构造 std::function 参数
Constructing std::function argument from lambda(从 lambda 构造 std::function 参数)...
2024-08-14 C/C++开发问题
25

STL BigInt 类实现
STL BigInt class implementation(STL BigInt 类实现)...
2024-08-14 C/C++开发问题
3

使用 std::atomic 和 std::condition_variable 同步不可靠
Sync is unreliable using std::atomic and std::condition_variable(使用 std::atomic 和 std::condition_variable 同步不可靠)...
2024-08-14 C/C++开发问题
17

在 STL 中将列表元素移动到末尾
Move list element to the end in STL(在 STL 中将列表元素移动到末尾)...
2024-08-14 C/C++开发问题
9

为什么禁止对存储在 STL 容器中的类重载 operator&amp;()?
Why is overloading operatoramp;() prohibited for classes stored in STL containers?(为什么禁止对存储在 STL 容器中的类重载 operatoramp;()?)...
2024-08-14 C/C++开发问题
6