myoukakuのブログ

C++でゲームエンジンを作っていきます。

static_mapのヘルパー関数、make_static_mapを書いた(1)

static_mapのヘルパー関数、make_static_mapを書いた(0) - myoukakuのブログ の続き

まず、以下のように書いてみました。

template <typename T, typename ... Types>
struct head
{
    using type = T;
};

template <typename ... Types>
struct key_type
{
    using type = typename head<Types...>::type::first_type;
};

template <typename ... Types>
struct value_type
{
    using type = typename head<Types...>::type::second_type;
};

template <
    typename ... Types,
    typename Key = key_type<Types...>::type,
    typename Value = value_type<Types...>::type,
    std::size_t N = sizeof...(Types)
>
static_map<Key, Value, N> make_static_map(Types&& ... args)
{
    return static_map<Key, Value, N> {{ args ... }};
}

はじめはmake_static_mapの引数をinitializer_listにしていたんですが、initializer_listのサイズがコンパイル時に取得できないので*1Variadic Templateを使うようにしました。

key_typeとvalue_typeのところはcommon_typeを使ったほうがいいんでしょうが、要素数が多くなるとエラーになったので*2先頭の型だけを使うようにしました。

これで

static const auto m = make_static_map(
    std::make_pair(Color::Red,    "Red"),
    std::make_pair(Color::Green,  "Green"),
    std::make_pair(Color::Blue,   "Blue"));

のように書けるようになりました。

型名と要素数を書く必要はなくなったので目的はほぼ達成できましたが、make_pairをいちいち書くのが面倒です。

static const auto m = make_static_map(
    { Color::Red,    "Red" },
    { Color::Green,  "Green" },
    { Color::Blue,   "Blue" });

と書けないかと試行錯誤しましたが、上手く行きませんでした。

続く。

*1:C++14からはsize()がconstexprになるのでたぶんOK

*2:500ぐらい?効率の良いcommon_typeを書けば回避できるかも。