2016-02-11 79 views
2

感谢一些技巧,我可以在编译时生成一个表,但表中的值并不是非常有用。例如,表格5x5看起来像这样:编译时间生成表

1,2,3,4,5, 
1,2,3,4,5, 
1,2,3,4,5, 
1,2,3,4,5, 
1,2,3,4,5, 

其中逗号是为了清晰目的。它创建该表的代码如下:

#include <iostream> 

using ll = long long; 

template<typename type,type...data> 
struct sequence 
{ 
    static type seq_data[sizeof...(data)]; 
    static const ll size; 
    type operator[](ll index){ 
     return seq_data[size-index-1]; 
    } 
}; 

template<typename type,type...data> 
type sequence<type,data...>::seq_data[sizeof...(data)] = { data... }; 
template<typename type,type...data> 
const ll sequence<type,data...>::size{sizeof...(data)}; 

template<ll n,ll l,ll...data> struct create_row 
{ 
    typedef typename create_row<n-1,l+1,l,data...>::value value; 
}; 
template<ll l,ll...data> 
struct create_row<0,l,data...> 
{ 
    typedef sequence<ll,data...> value; 
}; 

template<ll cols,ll rows> 
struct table 
{ 
    typename create_row<cols,1>::value row_data[rows]; 
    static const ll size; 
}; 

template<ll cols,ll rows> 
const ll table<cols,rows>::size{cols*rows}; 

using namespace std; 

int main() 
{ 
    table<5,5> my_table; 
    for(int i{0};i<5;i++) 
    { 
     for(int j{0};j<5;j++) 
     { 
      cout<<my_table.row_data[i][j]<<","; 
     } 
     cout<<endl; 
    } 
} 

正如你可以看到创建单列的我被迫在结构表使用硬编码的值“1”,因为这个原因create_table将始终返回相同的序列,序列号从1到n。出于这个原因,表中的每一行都具有相同的值。

什么是我想要做的是在编译时于各行的不同的初始值进行编码,以便有一个表,看起来像这样:

1,2,3,4,5, 
6,7,8,9,10, 
11 <CUT> 

我无法找到任何方式来创建一个这样的表格。

你有什么想法如何做到这一点?

+0

你是否试图在每次索引时都生成给定行的数据?你是否希望为表中的每个条目分配内存(就像在'std :: array'中一样?或者是“伪造”表格足够好([像这样](http://coliru.stacked-crooked.com/) a/51ac46f825dc22fd))? – AndyG

+0

不幸的是,你的解决方案对我来说并不好,我需要真正的表格。我发布的代码是通过元编程手段来构建pascal三角形的问题的一种简化。而不是任何真正使用的东西,我相信即使目前我没有工作实现,也可能会完成。 – fjanisze

+0

您的方法的主要问题是您试图生成表中的部分指出用户编入索引,如果表是在编译时完全生成的,那么索引到表中应该涉及索引到实际内存中;在运行时,我们必须知道我们索引到的类型。也就是说,'operation []'的结果必须是ak未知类型。 “序列”或“整数序列”等将数组编码为该类型;没有涉及的实际记忆。如果我们想用可变参数模板 – AndyG

回答

3

我不是在最后您的文章绝对相信你是否有兴趣在 -

  • 产生被编译时填充了一些功能f(i)的连续 值的矩阵环绕矩阵按行第一顺序,例如
 
    Cols = 3; Rows = 3; f(i) = 2i; Vals = (1,2,3,4,5,6,7,8,9) -> 

    |02|04|06| 
    ---------- 
    |08|10|12| 
    ---------- 
    |14|16|18| 

或: -

  • 生成一个矩阵,其中连续行是编译时填充 一些功能f(i)的连续值用于一些指定的初始i 每行,例如
 
    Cols = 3; f(i) = 3i; First_Vals = (4,7,10) -> 
    |12|15|18| 
    ---------- 
    |21|24|27| 
    ---------- 
    |30|33|36| 

反正有办法都做,这里是一个你可以用一个 C++ 14符合标准的编译使用。 (As @AndyG评论说,适用于编译时矩阵的 实现 - 利用标准库 - 是std::arraystd::array。)

#include <array> 
#include <utility> 

namespace detail { 

template<typename IntType, IntType(*Step)(IntType), IntType Start, IntType ...Is> 
constexpr auto make_integer_array(std::integer_sequence<IntType,Is...>) 
{ 
    return std::array<IntType,sizeof...(Is)>{{Step(Start + Is)...}}; 
} 

template<typename IntType, IntType(*Step)(IntType), IntType Start, std::size_t Length> 
constexpr auto make_integer_array() 
{ 
    return make_integer_array<IntType,Step,Start>(
     std::make_integer_sequence<IntType,Length>()); 
} 


template< 
    typename IntType, std::size_t Cols, 
    IntType(*Step)(IntType),IntType Start, std::size_t ...Rs 
> 
constexpr auto make_integer_matrix(std::index_sequence<Rs...>) 
{ 
    return std::array<std::array<IntType,Cols>,sizeof...(Rs)> 
     {{make_integer_array<IntType,Step,Start + (Rs * Cols),Cols>()...}}; 
} 

} // namespace detail 

/* 
    Return a compiletime initialized matrix (`std::array` of std::array`) 
    of `Cols` columns by `Rows` rows. Ascending elements from [0,0] 
    in row-first order are populated with successive values of the 
    constexpr function `IntType Step(IntType i)` for `i` in 
    `[Start + 0,Start + (Rows * Cols))` 
*/ 
template< 
    typename IntType, std::size_t Cols, std::size_t Rows, 
    IntType(*Step)(IntType), IntType Start 
> 
constexpr auto make_integer_matrix() 
{ 
    return detail::make_integer_matrix<IntType,Cols,Step,Start>(
     std::make_index_sequence<Rows>()); 
} 

/* 
    Return a compiletime initialized matrix (`std::array` of std::array`) 
    of `Cols` columns by `sizeof...(Starts)` rows. Successive rows are populated 
    with successive values of the constexpr function `IntType Step(IntType i)` 
    for `i` in `[start + 0,start + Cols)`, for `start` successively in `...Starts`. 
*/ 
template<typename IntType, std::size_t Cols, IntType(*Step)(IntType), IntType ...Starts> 
constexpr auto make_integer_matrix() 
{ 
    return std::array<std::array<IntType,Cols>,sizeof...(Starts)> 
     {{detail::make_integer_array<IntType,Step,Starts,Cols>()...}}; 
} 

您可以通过附加使演示程序:

#include <iostream> 

using namespace std; 

template<typename IntType> 
constexpr auto times_3(IntType i) 
{ 
    return i * 3; 
} 

static constexpr auto m4x6 = make_integer_matrix<int,4,6,&times_3<int>,4>(); 
static constexpr auto m5x1 = make_integer_matrix<int,5,&times_3<int>,7>(); 
static constexpr auto m6x5 = make_integer_matrix<int,6,&times_3<int>,11,13,17,19,23>(); 
static_assert(m4x6[0][0] == 12,""); 

int main() 
{ 
    cout << "A 4 x 6 matrix that wraps around in steps of `3i` from `i` = 4" << endl; 
    for (auto const & ar : m4x6) { 
     for (auto const & i : ar) { 
      cout << i << ' '; 
     } 
     cout << endl; 
    } 
    cout << endl; 
    cout << "A 6 x 5 matrix with rows of `3i` for initial `i` in <11,13,17,19,23>" 
     << endl; 
    for (auto const & ar : m6x5) { 
     for (auto const & i : ar) { 
      cout << i << ' '; 
     } 
     cout << endl; 
    } 
    cout << endl; 
    cout << "A 5 x 1 matrix with rows of of ` 3i` for initial `i` in <7>" 
     << endl; 
    for (auto const & ar : m5x1) { 
     for (auto const & i : ar) { 
      cout << i << ' '; 
     } 
     cout << endl; 
    } 

    return 0; 
} 

应该输出:

A 4 x 6 matrix that wraps around in steps of `3i` from `i` = 4 
12 15 18 21 
24 27 30 33 
36 39 42 45 
48 51 54 57 
60 63 66 69 
72 75 78 81 

A 6 x 5 matrix with rows of `3i` for initial `i` in <11,13,17,19,23> 
33 36 39 42 45 48 
39 42 45 48 51 54 
51 54 57 60 63 66 
57 60 63 66 69 72 
69 72 75 78 81 84 

A 5 x 1 matrix with rows of of ` 3i` for initial `i` in <7> 
21 24 27 30 33 

看到它at ideone

您可能也有兴趣std::experimental::make_array