問題描述
假設我有一些 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:數組的編譯時間計算的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!