C++20 enumで日本語を使いたい | consteval関数でassertを使う

はじめに

プログラミング言語C++ではenumが使えます。 しかしenumは日本語文字列が使えません。

enum class hoge { "青", "黄", "赤" };  // NG

日本語で書くにはどうするか。 ということで、以下のようにしてみました。

#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <string_view>
#include <utility>

class master {
    using value_type = std::pair<std::string_view, int>;

    // 装備名とIDのマスタデータ
    // このマスタデータは、実行時に持ち込まない
    static constexpr auto mst = std::array<value_type, 6>{{
        {"10.5cm連装砲", 160},
        {"10cm連装高角砲", 3},
        {"10cm連装高角砲(砲架)", 71},
        {"10cm連装高角砲+高射装置", 122},
        {"10cm連装高角砲改+増設機銃", 275},
        {"10cm連装高角砲群 集中配備", 464},
        // ...
    }};

    // マスタデータは二分探索できるようにソート済み
    static_assert(std::ranges::is_sorted(mst, {}, &value_type::first));

   public:

    // 装備名をキーにIDを得る
    static consteval int id(std::string_view name) {
        const auto itr = std::ranges::lower_bound(mst, name, {}, &value_type::first);
        
        // これらの表明は、constevalの実行時すなわちコンパイル時に行われる
        assert(itr != mst.end());
        assert(itr->first == name);
        
        // 引数の装備名がマスタに存在する場合にのみIDを返す
        // 存在しなければ上記assertによってコンパイルエラー
        return itr->second;
    }
};

namespace literals {

consteval int operator""_id(const char* str, std::size_t size) {
    return master::id(std::string_view{str, size});
}

}  // namespace literals

int main() {  //
    static_assert(master::id("10.5cm連装砲") == 160);

    {
        using literals::operator""_id;
        static_assert("10cm連装高角砲群 集中配備"_id == 464);
    }

    {
        using literals::operator""_id;
        // static_assert("100km連装砲"_id == 100);
    }
}