Я подозреваю, что это расширение существует именно потому, что не существует простого, переносимого способа достижения этого поведения. Вы можете эмулировать это, используя что-то вроде:
enum keys
{
key_alpha = 0,
key_beta = 1,
key_gamma = 2
};
struct ValType {
int v;
const char *name;
};
template <int key>
struct param;
#define SETPARAM(key,value1,value2) \
template <> \
struct param< (key) > { \
static constexpr ValType t {(value1),(value2)}; \
}
SETPARAM(key_alpha, 0x03b1,"alpha");
SETPARAM(key_gamma, 0x03b3,"gamma");
SETPARAM(key_beta, 0x03b2,"beta");
, который является переносимым и отвечает вашим требованиям, не будучи особенно "тяжелыми шаблонами".
Если вы не используете C ++ 11, вы все равно можете сделать это, но макрос, который специализируется на шаблоне param
, станет немного длиннее.
Модификация для использования как int i = someinput(); cout << param<i>::t.name;
Legal:
#include <cassert>
enum keys
{
key_alpha = 0,
key_beta = 1,
key_gamma = 2
};
struct ValType {
int v;
const char *name;
};
template <int key>
struct param {
enum { defined = false };
static constexpr ValType t {0, 0};
};
template <int key>
constexpr ValType param<key>::t;
static const int MAXPARAM=255;
#define SETPARAM(key,value1,value2) \
template <> \
struct param< (key) > { \
static_assert(key <= MAXPARAM, "key too big"); \
enum { defined = true }; \
static constexpr ValType t {(value1),(value2)}; \
}; \
constexpr ValType param<(key)>::t
template <int C=0>
struct get_helper {
static const ValType& get(int i) {
return i==0 ? (check(), param<C>::t) : get_helper<C+1>::get(i-1);
}
private:
static void check() {
assert(param<C>::defined);
}
};
template <>
struct get_helper<MAXPARAM> {
static const ValType& get(int) {
assert(false);
}
};
const ValType& GETPARAM(int key) {
return get_helper<>::get(key);
}
Хитрость заключается в том, чтобы создать экземпляр get_helper
и выполнить вызовы с помощью флага, который можно использовать для подтверждения правильности индекса. При необходимости вы можете увеличить MAXPARAM
, но это замедлит компиляцию.
Пример использования довольно прост:
#include "enumidx.hh"
#include <iostream>
SETPARAM(key_alpha, 0x03b1,"alpha");
SETPARAM(key_gamma, 0x03b3,"gamma");
SETPARAM(key_beta, 0x03b2,"beta");
int main() {
int key = key_beta;
const ValType& v = GETPARAM(key);
std::cout << v.name << std::endl;
}
Чтобы иметь более одного из них в любой данной программе, вы можете использовать анонимные пространства имен и / или сделать имя базы struct
(param
в этом примере) аргументом макроса и добавить другой макрос STARTPARAM
( ?) чтобы определить неспециализированный шаблон с таким именем.