Ein anderer Weg, den ich in einigen Codebasen gemacht habe, ist im Grunde genommen ein Typmerkmal, um Ihre Bereichsgrenzen mit zusätzlichen Informationen zu dekorieren.
Die Idee ist, dass Sie einige Merkmale wie
namespace mpl {
template <typename T>
struct GetEnumData;
}
Dann haben würden, wenn Sie einen „intelligenten“ Enum erklären, werden Sie auch diese Eigenschaft auf eine Struktur zu verknüpfen spezialisieren, die Metadaten über die scoped Enum enthält wie die rechtlichen Werte sind. Oder eine Liste von Strings, die den Namen der enum-Werte entsprechen, sodass Sie die enum-to-string-Konvertierung und zurück durchführen können.
enum class my_enum { a, b, c };
namespace mpl {
template<>
struct GetEnumData<my_enum> {
static constexpr std::size_t my_number = 3;
static const char * const my_strings []() {
return {"a", "b", "c"};
}
static const int my_values []() {
return {0, 1, 2};
}
}
} // end namespace mpl
N.B. Das Erzeugen des obigen Typenmerkmals ist ein wenig mühsam, daher verwenden Sie am Ende immer ein Makro für Ihre "Smart Enum" -Deklarationen. Wenn Sie Makros wirklich nicht mögen, ist dieser Ansatz nicht für Sie. Zumindest bis C++ in zukünftigen Versionen noch mehr Introspektions-Features hinzufügt (Daumen drücken).
Sobald Sie diese Art Trait obwohl, können Sie nützliche Dinge wie "enum_cast" tun, die eine Zeichenfolge zum Beispiel zu einer Aufzählung analysieren.
template <typename T>
T enum_cast(const std::string & input) {
using data = GetEnumData<T>;
for (std::size_t idx = 0; idx < data::my_number; ++idx) {
if (data::my_strings()[idx] == input) {
return static_cast<T>(data::my_values()[idx]);
}
}
throw bad_enum_value(input);
}
Und man konnte etwas ähnliches für int
‚s oder andere integrale Arten tun.
Das Verhalten ist nicht undefiniert. Abschnitt 7.2, Absatz 10 sagt "Ein Ausdruck der arithmetischen oder Aufzählungstyp kann explizit in einen Aufzählungstyp konvertiert werden. Der Wert ist unverändert, wenn es im Bereich der Aufzählungswerte des Aufzählungstyps ist; ** andernfalls ist der resultierende Aufzählungswert nicht angegeben **. " Der Wert ist also nicht spezifiziert, aber das Verhalten ist nicht undefiniert (keine nasalen Dämonen). – Cornstalks
@Cornstalks, danke für den Hinweis. Das ist definitiv besser als nicht definiert. Dennoch steht die Frage: Gibt es eine nette Möglichkeit festzustellen, ob der Wert ungültig ist? – toth
mir ist leider nicht bekannt. – Cornstalks