Очевидная вещь - комментировать ваше перечисление:
// generic code
#include <algorithm>
template <typename T>
struct enum_traits {};
template<typename T, size_t N>
T *endof(T (&ra)[N]) {
return ra + N;
}
template<typename T, typename ValType>
T check(ValType v) {
typedef enum_traits<T> traits;
const T *first = traits::enumerators;
const T *last = endof(traits::enumerators);
if (traits::sorted) { // probably premature optimization
if (std::binary_search(first, last, v)) return T(v);
} else if (std::find(first, last, v) != last) {
return T(v);
}
throw "exception";
}
// "enhanced" definition of enum
enum e {
x = 1,
y = 4,
z = 10,
};
template<>
struct enum_traits<e> {
static const e enumerators[];
static const bool sorted = true;
};
// must appear in only one TU,
// so if the above is in a header then it will need the array size
const e enum_traits<e>::enumerators[] = {x, y, z};
// usage
int main() {
e good = check<e>(1);
e bad = check<e>(2);
}
Вам нужно, чтобы массив обновлялся до e
, что неприятно, если вы не автор e
. Как говорит Sjoerd, это может быть автоматизировано с любой приличной системой сборки.
В любом случае вы против 7,2 / 6:
Для перечисления, где emin - это
наименьший перечислитель и emax является
Наибольшие значения перечисления
значения базового типа
в диапазоне от bmin до bmax, где bmin
и bmax, соответственно,
наименьшие и самые большие значения
наименьшее битовое поле, которое может хранить emin
и emax. Можно определить
перечисление, которое имеет значения не
определяется любым из его перечислителей.
Поэтому, если вы не являетесь автором e
, вы можете или не можете гарантировать, что действительные значения e
действительно появятся в его определении.