static_mapのヘルパー関数、make_static_mapを書いた(2)
static_mapのヘルパー関数、make_static_mapを書いた(1) - myoukakuのブログ の続き
static const auto m = make_static_map( Color::Red, std::string("Red"), Color::Green, std::string("Green"), Color::Blue, std::string("Blue"));
と書けるmake_static_map関数を実現する方法を考えます。
方針としては、与えられた引数をtupleにし、そのtupleの偶数番目と奇数番目をpairにしてそれをstatic_mapに渡すようにします。 コードのイメージとしてはこんな感じです。
template <typename ... Types> /* 戻り値の型は省略 */ make_static_map(Types...args) { const auto t = std::make_tuple(args...); return { std::make_pair(std::get<0>(t), std::get<1>(t)), std::make_pair(std::get<2>(t), std::get<3>(t)), std::make_pair(std::get<4>(t), std::get<5>(t)), . . . }; }
このためには偶数のリスト(0, 2, 4, ...)と奇数のリスト(1, 3, 5, ...)が必要です。 それにはindex_tuple技法を使います。
参考
要点だけを抜き出したコードがこちら
template < typename TupleType, std::size_t ... EvenIndexes, std::size_t ... OddIndexes, > /* 省略 */ make_static_map_aux( TupleType t, index_tuple<EvenIndexes...>, index_tuple<OddIndexes...>) { return { std::make_pair( std::get<EvenIndexes>(t), std::get<OddIndexes>(t) )... }; } template < typename ... Types, std::size_t N = sizeof...(Types) > /* 省略 */ make_static_map(Types...args) { return make_static_map_aux( std::make_tuple(args...), index_range<0, N, 2>::type(), index_range<1, N, 2>::type()); }
index_range<0, N, 2>::type()で偶数のリストを、index_range<1, N, 2>::type()で奇数のリストを作って渡します。 make_static_map_aux内でのパラメータパックの展開の仕方がミソです。
これで望み通りの記述が可能になりました。メデタシメデタシ。
…とはいかず、引数が多くなるとmake_tupleの部分でInternal Compiler Error(fatal error C1060: ヒープの領域を使い果たしました。)になってしまいました*1。私の環境では引数の数が80を超えたあたりでエラーになりました。
これでは使い物になりません。
続く。
*1:Visual Studio 2013