Lo obvio es anotar tu enumeración:
#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) {
if (std::binary_search(first, last, v)) return T(v);
} else if (std::find(first, last, v) != last) {
return T(v);
}
throw "exception";
}
enum e {
x = 1,
y = 4,
z = 10,
};
template<>
struct enum_traits<e> {
static const e enumerators[];
static const bool sorted = true;
};
const e enum_traits<e>::enumerators[] = {x, y, z};
int main() {
e good = check<e>(1);
e bad = check<e>(2);
}
Necesita que la matriz se mantenga actualizada e, lo cual es una molestia si no es el autor de e. Como dice Sjoerd, probablemente se pueda automatizar con cualquier sistema de compilación decente.
En cualquier caso, te enfrentas a 7.2 / 6:
Para una enumeración donde emin es el enumerador más pequeño y emax es el más grande, los valores de la enumeración son los valores del tipo subyacente en el rango de bmin a bmax, donde bmin y bmax son, respectivamente, los valores más pequeño y más grande del más pequeño. campo de bits que puede almacenar emin y emax. Es posible definir una enumeración que tenga valores no definidos por ninguno de sus enumeradores.
Por lo tanto, si no es el autor de e, puede que tenga o no una garantía de que los valores válidos de erealmente aparezcan en su definición.
enum e{x = 10000};¿En este caso9999cae dentro del rango deenum?