2013-09-25 23 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