2013-09-25 50 views
11

我期待創造座標的查找表,是這樣的:查找表constexpr

int a[n][2] = {{0,1},{2,3}, ... } 

對於給定的n,在編譯時被創建。我開始尋找到constexpr,但好像返回constexpr std::vector<std::array <int, 2> >不是一個選項的功能,因爲我得到:

invalid return type 'std::vector<std::array<int, 2ul> >' of constexpr function 

如何創建這樣的編譯時間陣列?

+1

'的std :: VECTOR'不是文本類型,並且因此不能用於C++ 11'constexpr'。 C++ 11的'array'類型缺少'constexpr'訪問器,因此在'constexpr'函數中的使用也受到限制。如果您沒有一些C++ 1y庫/編譯器支持,我建議使用自定義數組類型。 – dyp

+0

@DyP - 你能舉一個例子嗎? – nbubis

+0

如果你添加了一些你想要做的細節,會更有用;) – dyp

回答

15

我會先轉儲代碼,稍後在必要/適當的地方添加引用和註釋。如果結果與您正在尋找的結果稍微接近,請留下評論。

指數包擴展的技巧(這裏要求應用發生器),由Xeo,從this answer,修改爲使用std::size_t而不是unsigned

#include <cstddef> 

// by Xeo, from https://stackoverflow.com/a/13294458/420683 
template<std::size_t... Is> struct seq{}; 
template<std::size_t N, std::size_t... Is> 
struct gen_seq : gen_seq<N-1, N-1, Is...>{}; 
template<std::size_t... Is> 
struct gen_seq<0, Is...> : seq<Is...>{}; 

發電機功能:

#include <array> 

template<class Generator, std::size_t... Is> 
constexpr auto generate_array_helper(Generator g, seq<Is...>) 
-> std::array<decltype(g(std::size_t{}, sizeof...(Is))), sizeof...(Is)> 
{ 
    return {{g(Is, sizeof...(Is))...}}; 
} 

template<std::size_t tcount, class Generator> 
constexpr auto generate_array(Generator g) 
-> decltype(generate_array_helper(g, gen_seq<tcount>{})) 
{ 
    return generate_array_helper(g, gen_seq<tcount>{}); 
} 

用例:

// some literal type 
struct point 
{ 
    float x; 
    float y; 
}; 
// output support for `std::ostream` 
#include <iostream> 
std::ostream& operator<<(std::ostream& o, point const& p) 
{ return o << p.x << ", " << p.y; } 

// a user-defined generator 
constexpr point my_generator(std::size_t curr, std::size_t total) 
{ 
    return {curr*40.0f/(total-1), curr*20.0f/(total-1)}; 
} 

int main() 
{ 
    constexpr auto first_array = generate_array<5>(my_generator); 
    constexpr auto second_array = generate_array<10>(my_generator); 

    std::cout << "first array: \n"; 
    for(auto p : first_array) 
    { 
     std::cout << p << '\n'; 
    } 
    std::cout << "========================\n"; 

    std::cout << "second array: \n"; 
    for(auto p : second_array) 
    { 
     std::cout << p << '\n'; 
    } 
} 
+1

哇 - 這是很多代碼!這真的是最短的方式嗎? – nbubis

+0

@nbubis這是一個非常通用的解決方案。如果您縮小/更精確地指定您想要的內容,可能會有一個不太詳細的解決方案。 – dyp

+0

我認爲他的使用示例正是我正在尋找的內容,但是確實有很多額外的代碼:) – nbubis

-1

有關使用GNU的gperf或某種其他代碼生成工具什麼?

+1

嗨。你能在編譯時使用gperf來初始化一個向量嗎?如果是這樣? –

14

隨着C++ 14,你不需要太多的模板魔法。這裏的如何有一個查找表用於f(x) = x^3用一個例子的第一座標是所述x值和第二座標是所述f(x)值:

#include <iostream> 

template<int N> 
struct Table 
{ 
    constexpr Table() : values() 
    { 
     for (auto i = 0; i < N; ++i) 
     { 
      values[i][0] = i; 
      values[i][1] = i * i * i; 
     } 
    } 
    int values[N][2]; 
}; 

int main() { 
    constexpr auto a = Table<1000>(); 
    for (auto x : a.values) 
     std::cout << "f(" << x[0] << ") = " << x[1] << '\n'; 
} 
+0

真的很好!非常多的C++ 1x可以學習.. – nbubis

+0

在constexpr中的':values()'是什麼意思Table():values()'?它是否初始化或什麼? – Jonas

+0

&Jonas是的,它會初始化哪些是必要的,因爲C++需要一個編譯常量值。它將在後面的構造函數中設置,但編譯器難以追蹤 – IceFire