2013-05-08 10 views
19

Einige Typumwandlungen in <type_traits> können auch mit Kernsprachsyntax ausgedrückt werden (z. B. std::add_const<T>::type ist/entspricht const T). Dto für std::add_lvalue_reference und vielleicht andere. Was nützen diese Typeigenschaften?Anwendungsfälle für std :: add_const und ähnliche

Ich verstehe der Standard würde eine „unvollständige Toolbox“, ohne sie zur Verfügung stellen, und ich kann die Verwendung in einer Meta-Art und Weise, in etwa so vorstellen:

template<typename In, template <typename> class Modifier> 
struct Apply { 
    typedef typename Modifier<T>::type Out; 
}; 

Apply<int, std::add_const> 

es andere Anwendungsfälle für diese Züge welche können syntaktisch ausgedrückt werden oder sind sie nur "aus einem Gefühl der Vollständigkeit" und für den gelegentlichen Meta-Gebrauch enthalten?

+1

Was passiert, wenn 'T' bereits' const' ist? –

+1

@PeterWood [Funktioniert gut] (http://ideone.com/mhY62n), zumindest in gcc 4.7.2 – Angew

+2

@PeterWood Wenn es bereits qualifiziert ist, gibt es den gleichen Typ zurück, wie vom Standard gefordert. – jrok

Antwort

19

Diese Züge kommen aus Boost und dem Vorschlag sie den Standard hinzuzufügen, N1345, zitiert Andrei Alexandrescu mit den Worten:

„Ich habe die Symmetrie Argument verstehe add_const zum Hinzufügen, add_volatile, add_cv und add_pointer, Ich würde jedoch dafür plädieren, sie zu eliminieren. Die von der Sprache bereitgestellten Entsprechungen sind einfach und schön. "

Der gleiche Vorschlag gibt auch diese Begründung:

Anmerkung des Autors: oberflächlich die add_const, add_volatile und add_cv Klassen irrelevant sind, da zum Beispiel add_const :: Typ des gleichen wie T const ist, für alle T (derzeit gilt das nicht für Funktionstypen - aber issue 295 adressiert dies). Die Erfahrung von Boost ist jedoch, dass mehrere Benutzer aus folgenden Gründen gebeten haben, dass diese Vorlagen in der Bibliothek vorhanden sind: (a) Einige Benutzer finden diese expliziter - wenn sie insbesondere Transformationsvorlagen kombinieren, mögen Nutzer die Art von "eingebaut" Dokumentation ", die diese Vorlagen bereitstellen. (b) Nicht alle Benutzer sind sich bewusst, dass das cv-Qualifizieren einer Referenz erlaubt ist und keine Auswirkungen hat, oder dass cv-qualifizieren eines Typs, der bereits cv-qualifiziert ist, erlaubt ist und keine Wirkung hat. (c) Compiler können Warnungen ausgeben, wenn cv-qualifying einen Typ, der eine Referenz ist, oder bereits einen cv-Qualifier hat, diese Templates können so implementiert werden, dass diese Nachrichten in diesen Fällen unterdrückt werden.

Auch für add_reference (bis add_lvalue_reference im Standard umbenannt):

Hinweis Verfasser: die add_reference Vorlage einer der ursprünglichen Motivationen hinter der Bibliothek Boost-Typ Züge war. Die Auflösung auf issue 106 lässt die Vorlage jedoch weitgehend redundant erscheinen. Trotzdem kann addreference sehr nützlich sein, um Compiler-Warnungen zu unterdrücken, wenn versehentlich Referenzen auf Referenzen im Template-Code erzeugt werden.

+4

' add_ {l, r} value_reference' spielt auch gut mit 'void' . – Xeo

5

Diese Merkmale sind für gelegentliche Meta-Verwendung vorgesehen. Es ermöglicht den Transport erwünschter CV-Qualifier in der Meta-Programmierung.

template<class T,template<class> class Trait> 
struct transform 
{ 
    /* working with T creating newT*/ 

    typedef Trait<newT>::type type; 
}; 

template<class T> 
struct special_transform 
    : transfrom<T, std::add_const> 
{}; 

In diesem Fall können Sie nicht std::add_const mit const ersetzen.

struct F 
{ 
    bool f() const { return true; } 
    bool f() { return false; } 
}; 
assert(!F{}.f()) 
assert(std::add_const_t<F>{}.f()); 

Es benötigt auch für die Prüfung von cv-ref-qualifizierten Mitglied-Funktionen Funktionalität, die für lref- für verschiedene Überlastungen (nur dadurch unterscheidet, kann:

1

Der einzige Anwendungsfall ich weiß, ist unten dargestellt qualifiziert modern C++ hat praktisch std::as_const Funktion):

struct F 
{ 
    int g() & { return 1; } 
    int g() const & { return 2; } 
    int g() && { return 3; } 
    int g() const && { return 4; } 
}; 
F f; 
assert(f.g() == 1); 
assert(std::as_const(f).g() == 2); 
assert(F{}.g() == 3); 
assert(std::add_const_t<F>{}.g() == 4); // rarely needed, but if needed, then it helps 
1

add_const verwendet werden kann, um Typ-Abzug Konflikte zu lösen.

template <typename T> 
class wrapper; 

template <typename T> 
bool operator==(wrapper<T> const& w, T const& t); 

Probleme entstehen, wenn wir wrapper<T const> verwenden:

wrapper<int const> w = { 42 }; 
assert(w == 42); // Error: conflicting deduced types 

T gleichzeitig abgeleitet beide intundint const sein. Dies kann gelöst werden mit add_const:

template <typename T> 
bool operator==(wrapper<T> const& w, add_const_t<T>& t); 
+0

Interessanter Anwendungsfall. Alles andere, was den zweiten Funktionsparameter zu einem nicht-abgeleiteten Kontext machen würde, würde auch funktionieren, aber dieser ist ziemlich prägnant. – Angew

Verwandte Themen