2016-07-11 15 views
3

私は、C++ 14バリデーションテンプレートを使用してコンパイル時ルックアップテーブルを作成したいと思います。 私はそこだ瞬間: C++ 14コンパイル時std :: array with variadic templates

static const unsigned kCount = 5; 

template<unsigned Index> 
constexpr auto getRow(void) 
{ 
    return std::array<unsigned, 2> { Index, Index * Index }; 
} 

template<unsigned... Indices> 
constexpr auto generateTable(std::index_sequence<Indices...>) 
{ 
    return std::array<std::array<unsigned, 2>, sizeof...(Indices)> 
    { 
     // This is were I'm stuck. How to build a std::array using Indices as template parameter in getRow()? 
    }; 
} 

constexpr auto generate(void) 
{ 
    return generateTable(std::make_index_sequence<kCount>{}); 
} 

私はテーブルがstd::arrayになりたいです。各行は2列のstd::arrayで構成されています。私はgenerateTable()に立ち往生しています。私は何とかインデックスをgetRow()に渡してテンプレートパラメータとして渡す必要があります。

これはstd::integer_sequenceとテンプレートパラメータパックの拡張を使用して達成可能ですか、それとも自分で再帰を実装する必要がありますか?

getRow()が簡略化されている - 。値の種類は、実際にテンプレートの種類から来ているIndex * Indexは単なるプレースホルダである私は、パラメータパックの拡張を使用してgetRow()を呼び出す方法の方法を知っておく必要があります。。)

+0

「インデックス」とは何ですか?行番号? – Arunmu

+0

はい、インデックスは行番号です。現在0から4まで動いています。 – Wum

答えて

9

あなたがしているように見えますほぼそこに。

return std::array<std::array<unsigned, 2>, sizeof...(Indices)> 
{ 
    getRow<Indices>()... 
}; 

getRow<Indices>()...ラインがに展開されます:ちょうどパラメータパックの展開に頼るKyleKnoepfelの解決のために

getRow<0>(), getRow<1>(), ..... , getRow<sizeof...(Indices)-1>() 
+0

ああ、クール、thats it。ありがとうございました... – Wum

4

+1が、私は私のAMD64のlinuxでコードをコンパイルする問題を抱えている」ので、エラー: 'generateTable'への呼び出しに一致する関数がありません。 "および"候補テンプレートが無視されました:置換エラー:推定された非型テンプレート引数に対応するテンプレートパラメータと同じ型がありません( '符号なしlong'と 'unsigned int' "

問題はstd::make_index_sequence<kCount>{}std::size_tのシーケンスを生成することです。 std::size_tunsigned intと定義されている場合、すべてうまくいく。 std::size_t(私のプラットフォームで同じよう)unsigned longとして定義されている場合、次の宣言は

template<unsigned... Indices> 
constexpr auto generateTable(std::index_sequence<Indices...>) 

提案動作しませんでした。代わりに使用unsignedこれまでstd::size_tを。特に

template<std::size_t ... Indices> 
constexpr auto generateTable(std::index_sequence<Indices...>) 

エンアンパッサン、(括弧の唯一のレベル)、それはC++ 14が、(私見)に完全に合法だ、私はそれが古い(C++ 11)構文を使用する方が良いと思う{ val1, val2 }std::arrayを初期化します二重レベルのブレース({ { val1, val2 } });下位互換性(Wumによって指摘されているように)といくつかのコンパイラ(clang ++ 3.5のような)で迷惑な警告を避けるためです。だから私はp.s:私の悪い英語のため申し訳ありませんので、

return std::array<unsigned, 2> { { Index, Index * Index } }; 

return std::array<std::array<unsigned, 2>, sizeof...(Indices)> 
{ { getRow<Indices>() ... } }; 

、配列宣言/初期化中括弧の第二のレベルを使用することをお勧めします。

+0

'std :: size_t'に関するヒントをありがとう。私はこれを念頭に置いておきます。中括弧の第2レベルの利点について説明してください。 – Wum

+0

'std :: size_t'勧告をUpvoteしますが、なぜ二重ブレースを推奨しますか? – CoffeeandCode

+0

http:// ja。cppreference.com/w/cpp/container/arrayは、C++ 11で 'std :: array'の集合初期化を維持するために二重の括弧が必要であることを示しています。これは後方互換性の問題であるようです。 – Wum

関連する問題