Bisher kann ich nichts ELI5 online finden. Für ein Lernprojekt möchte ich mein eigenes is_constructible implementieren. Kann jemand bitte erklären, wie es funktioniert?Wie wird std :: is_constructible <T, Args> implementiert?
Antwort
Von cppreference:
[I] f die Variablendefinition
T obj(std::declval<Args>()...);
wohlgeformt ist,value
gleichtrue
, sonstvalue
false
ist.
prüfen, ob Code wohlgeformt mit SFINAE Techniken durchgeführt wird, zum Beispiel des void_t<>
Trick (erwarteten Teil der C++ 1z Standardbibliothek sein):
template <class...>
using void_t = void;
template <class, class T, class... Args>
struct is_constructible_ : std::false_type {};
template <class T, class... Args>
struct is_constructible_<
void_t<decltype(T(std::declval<Args>()...))>,
T, Args...> : std::true_type {};
template <class T, class... Args>
using is_constructible = is_constructible_<void_t<>, T, Args...>;
Der using
hoop -Hopping ist da, um das void_t<>
Argument zuerst zu platzieren. Es kommt normalerweise mit einem Standardtyp, aber diese Position wird vom variadic Args
Pack gehalten.
Wenn is_constructible_
für <void, T, Args...>
instanziiert wird, versucht der Compiler zuerst, die Spezialisierung zu instanziieren. Dies ist nur dann erfolgreich, wenn der Inhalt von void_t<...>
semantisch gültig ist, dh T(std::declval<Args>()...)
korrekt ausgeführt werden kann - wie in den Anforderungen von is_constructible
angegeben. Beachten Sie, dass ich eine temporäre anstelle einer lokalen Variable verwendet habe, aber meines Wissens ändern sich die Regeln nicht zwischen den beiden. Die Spezialisierung erbt von std::true_type
, was eine true
value
ergibt.
Wenn die Spezialisierung nicht instanziiert werden kann (d. H. T(std::declval<Args>()...)
ist nicht gültig), greift der Compiler auf die allgemeine Vorlage zurück, die immer instanziiert werden kann. Dieser erbt von std::false_type
, was die false
value
ergibt.
Genauere Züge, wie std::is_trivially_constructible
, benötigen erweiterte Kenntnisse der Sprachregeln der Ausdruck, dessen Gültigkeit Handwerk sollte der Wert des Merkmals werden. Wenn dies innerhalb der Sprache nicht durchführbar ist, wie beispielsweise mit , dann muss der Compiler selbst eine intrinsische Funktion bereitstellen, um den Wert abzurufen.
Das war eine ausgezeichnete Erklärung, danke! – Alex
Dies ist nicht genau äquivalent zu 'std :: is_constructible', weil' T (Arg) 'äquivalent zu einer C-Style-Besetzung ist - also ist deine' is_constructible '' true', während die ' Std wird man falsch zurückgeben. –