Werde ich Schritt auf eine UB [...]
Technisch ja. Aber praktisch kompiliert es nicht nur für Nicht-Aufzählungstypen. Wenn Sie schreiben:
std::conditional_t<std::is_enum<T>::value, std::underlying_type_t<T>, foo>;
^^^^^^^^^^^^^^^^^^^^^^^^^
Das Template-Parameter muss vor die conditional
Vorlage ausgewertet werden instanziiert werden kann. Dies ist äquivalent zu allen Funktionsargumenten, die aufgerufen werden müssen, bevor der Rumpf der Funktion beginnt. Für nicht aufgezählte Typen ist underlying_type<T>
unvollständig (sicher ist es im Standard als undefiniert angegeben, aber lasst uns vernünftig sein), also gibt es kein underlying_type_t
. Daher schlägt die Instanziierung fehl.
Was müssen Sie tun, ist Verzögerung die Instanziierung in diesem Fall:
template <class T> struct tag { using type = T; };
typename std::conditional_t<
std::is_enum<T>::value,
std::underlying_type<T>,
tag<foo>>::type;
Nun, unsere conditional
statt der Auswahl Typen ist die Auswahl eines metafunction! underlying_type<T>::type
wird nur instanziiert, wenn T
eine Enumeration ist. Wir müssen außerdem foo
umhüllen, um es in eine Metafunktion umzuwandeln.
Dies ist ein gemeinsames Muster und war eine besondere Sache in Boost.MPL eval_if
genannt, die aussehen würde:
template <bool B, class T, class F>
using eval_if_t = typename std::conditional_t<B, T, F>::type;
Bitte beachte, dass wir mit beiden conditional_t
und::type
.
UB passiert zur Laufzeit, Template-Funktionen wie diese erledigen ihre Arbeit zur Kompilierzeit. Wie für "wird es löschen $ HOME" siehe [Chandler's Gespräch] (https://www.youtube.com/watch?v=yG1OZ69H_-o) – Borgleader
Dies ist Kompilierzeit Auswertung, keine Laufzeit. Sie werden hier nicht auf UB stoßen. – AndyG
@Borgleader OK "wird die resultierende Binärdatei möglicherweise mein $ HOME löschen?" Eigentlich bin ich mir nicht einmal sicher, ob es ein UB zum Schreiben von 'std :: soundly_type_t' gerade (ohne 'std :: conditional') gibt. Bedeutet" soll ", dass seine Verletzung zu einem schlecht geformten Programm führt? –
nodakai