Найти правильную константу макроса в функции constexpr класса шаблона

Существует заголовок C с очень длинным списком макроконстантов, подобным этому:

#define MODE_1_A 101
#define MODE_1_AB 21
#define MODE_1_ABC 9901
#define MODE_2_A 1031
#define MODE_2_AB 347
#define MODE_2_ABC 692
...

В то время как имена макросов следуют очень регулярному шаблону, к сожалению, нет способа надежного вычисления константы.

Я хотел бы написать класс шаблона, который может возвращать правильное целое целое как constexpr.

template<unsigned c,="" unsigned="" m="">
struct MyClass
{
 constexpr int mode() {
 // C = 1 & M == 1 => return MODE_1_A
 // C = 1 & M == 2 => return MODE_1_AB
 // and so on
 }
 ... // a lot of additional code
};
</unsigned>

Что это лучший способ, чтобы написать constexpr функцию mode?

3 ответа

Вы можете специализировать метод:

template<unsigned c,="" unsigned="" m="">
struct MyClass
{
 static constexpr int mode();
};

template<> constexpr int MyClass<1, 1>::mode() { return 101; }
template<> constexpr int MyClass<1, 2>::mode() { return 21; }
</unsigned>

И с помощью TAG(N, C) из макроса для отображения целого числа в строку для токена:

#define DEFINE_MODE(N,C) \
 template<> constexpr int MyClass<n, c="">::mode() { return TAG(N, C); }

DEFINE_MODE(1, 1)
DEFINE_MODE(1, 2)
DEFINE_MODE(2, 1)
// ...
</n,>


Используйте препроцессор! Использование библиотеки Boost.Preprocessor:

#include <boost preprocessor.hpp="">
#define BOOST_PP_LOCAL_MACRO(n) \
 template<> struct MyClass<n, 1=""> { \
 constexpr int mode() { return BOOST_PP_CAT(BOOST_PP_CAT(MODE_, n), _A); } }; \
 template<> struct MyClass<n, 2=""> { \
 constexpr int mode() { return BOOST_PP_CAT(BOOST_PP_CAT(MODE_, n), _AB); } }; \
 template<> struct MyClass<n, 3=""> { \
 constexpr int mode() { return BOOST_PP_CAT(BOOST_PP_CAT(MODE_, n), _ABC); } }; \
#define BOOST_PP_LOCAL_LIMITS (1, 10)
#include BOOST_PP_LOCAL_ITERATE()
</n,></n,></n,></boost>


Вы можете использовать макрос:

#define MODE(a,b) MODE_##a##_##b

Затем используйте его следующим образом:

std::cout << MODE(2,ABC) << std::endl;

Ваш вопрос пропустит информацию о том, как сшить целое число M в строки A, AB, ABC... Кроме того, всегда ли C и M знают во время компиляции или могут быть переменным параметром для некоторой внешней функции?

licensed under cc by-sa 3.0 with attribution.