Поскольку std::map
не имеет аргументов constexpr, аргумент шаблона str_map["BB"]
не может быть оценен во время компиляции.
Простой и понятный способ сопоставления целых чисел с типами будет использовать std::tuple
и std::tuple_element
следующим образом.
Например, StrType<0>
равно char
, StrType<1>
равно int
и т. Д.
using types = std::tuple<char, int, float, std::complex<double>>;
template<std::size_t N>
using StrType = typename std::tuple_element<N, types>::type;
Тогда проблема в том, как сопоставить строки с целыми числами в C ++ 11.
Во-первых, строки можно сравнить во время компиляции с помощью принятого ответа в этом посте.
Во-вторых, мы можем использовать троичный оператор в вычислениях во время компиляции.
Таким образом, по крайней мере, следующая функция getIdx
может сопоставить каждую строку с соответствующим целым числом во время компиляции.
Например, getIdx("AA")
равен нулю:
constexpr bool strings_equal(const char* a, const char* b) {
return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1));
}
constexpr std::size_t getIdx(const char* name)
{
return strings_equal(name, "AA") ? 0:
strings_equal(name, "BB") ? 1:
strings_equal(name, "CC") ? 2:
strings_equal(name, "DD") ? 3:
4; // compilation error
}
Вы можете использовать эти функции для текущей цели следующим образом:
DEMO
StrType<getIdx("BB")> x; // x is int.
constexpr const char* float_type = "CC";
StrType<getIdx(float_type)> y; // y is float.
static_assert(std::is_same<StrType<getIdx("AA")>, char> ::value, "oops."); // OK.
static_assert(std::is_same<StrType<getIdx("BB")>, int> ::value, "oops."); // OK.
static_assert(std::is_same<StrType<getIdx("CC")>, float>::value, "oops."); // OK.
static_assert(std::is_same<StrType<getIdx("DD")>, std::complex<double>>::value, "oops."); // OK.