La chose la plus évidente consiste à annoter votre enum:
// 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);
}
Vous avez besoin de la matrice pour être tenu à jour avec e
, ce qui est une nuisance si vous n'êtes pas l'auteur de l' e
. Comme Sjoerd dit, il peut probablement être automatisé à l'aide de tout bon système de construction.
Dans tous les cas, vous êtes contre 7.2/6:
Pour une énumération où emin est l'
le plus petit agent recenseur et emax est l'
plus grand, les valeurs de l'énumération
sont les valeurs du type sous-jacent
dans la gamme bmin à bmax, où bmin
et bmax sont, respectivement, la
la plus petite et la plus grande des valeurs de la
plus petit champ qui permet de stocker emin
et emax. Il est possible de définir une
l'énumération qui a des valeurs non
défini par l'une quelconque de ses agents recenseurs.
Donc, si vous n'êtes pas l'auteur de l' e
, vous peut ou peut ne pas avoir la garantie que les valeurs valides de e
fait apparaître dans sa définition.