2016-02-11 104 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