Typalias, Alias-Template (seit C++11)
Ein Typalias ist ein Name, der sich auf einen zuvor definierten Typ bezieht (ähnlich wie typedef).
Ein Alias-Template ist ein Name, der sich auf eine Familie von Typen bezieht.
Inhalt |
[bearbeiten] Syntax
Alias-Deklarationen sind Deklarationen mit der folgenden Syntax
using identifier attr (optional) = type-id ; |
(1) | ||||||||
template < template-parameter-list >
|
(2) | ||||||||
template < template-parameter-list > requires constraint
|
(3) | (seit C++20) | |||||||
| attr | - | optionale Sequenz von beliebig vielen Attributen |
| identifier | - | der durch diese Deklaration eingeführte Name, der entweder ein Typname (1) oder ein Template-Name (2) wird |
| template-parameter-list | - | Template-Parameterliste, wie in Template-Deklaration |
| constraint | - | ein Constraint-Ausdruck, der die vom Alias-Template akzeptierten Template-Parameter einschränkt |
| type-id | - | abstrakter Deklarator oder ein anderer gültiger type-id (der einen neuen Typ einführen kann, wie in type-id vermerkt). Der type-id darf sich nicht direkt oder indirekt auf identifier beziehen. Beachten Sie, dass der Deklarationspunkt des Identifiers das Semikolon nach type-id ist. |
[bearbeiten] Erklärung
template<class T> struct Alloc {}; template<class T> using Vec = vector<T, Alloc<T>>; // type-id is vector<T, Alloc<T>> Vec<int> v; // Vec<int> is the same as vector<int, Alloc<int>>
Wenn das Ergebnis der Spezialisierung eines Alias-Templates ein abhängiges template-id ist, werden nachfolgende Ersetzungen auf dieses template-id angewendet.
template<typename...> using void_t = void; template<typename T> void_t<typename T::foo> f(); f<int>(); // error, int does not have a nested type foo
Der Typ, der bei der Spezialisierung eines Alias-Templates erzeugt wird, darf seinen eigenen Typ nicht direkt oder indirekt verwenden.
template<class T> struct A; template<class T> using B = typename A<T>::U; // type-id is A<T>::U template<class T> struct A { typedef B<T> U; }; B<short> b; // error: B<short> uses its own type via A<short>::U
Alias-Templates werden niemals durch Template-Argument-Deduktion abgeleitet, wenn ein Template-Template-Parameter abgeleitet wird.
Es ist nicht möglich, ein Alias-Template partiell oder explizit zu spezialisieren.Wie jede Template-Deklaration kann ein Alias-Template nur im Klassen-Scope oder Namensraum-Scope deklariert werden.
|
Der Typ eines Lambda-Ausdrucks, der in einer Alias-Template-Deklaration vorkommt, ist zwischen Instanziierungen dieses Templates unterschiedlich, auch wenn der Lambda-Ausdruck nicht abhängig ist. template<class T> using A = decltype([] {}); // A<int> and A<char> refer to different closure types |
(seit C++20) |
[bearbeiten] Hinweise
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_alias_templates |
200704L |
(C++11) | Alias-Templates |
[bearbeiten] Schlüsselwörter
[bearbeiten] Beispiel
#include <iostream> #include <string> #include <type_traits> #include <typeinfo> // type alias, identical to // typedef std::ios_base::fmtflags flags; using flags = std::ios_base::fmtflags; // the name 'flags' now denotes a type: flags fl = std::ios_base::dec; // type alias, identical to // typedef void (*func)(int, int); using func = void (*) (int, int); // the name 'func' now denotes a pointer to function: void example(int, int) {} func f = example; // alias template template<class T> using ptr = T*; // the name 'ptr<T>' is now an alias for pointer to T ptr<int> x; // type alias used to hide a template parameter template<class CharT> using mystring = std::basic_string<CharT, std::char_traits<CharT>>; mystring<char> str; // type alias can introduce a member typedef name template<typename T> struct Container { using value_type = T; }; // which can be used in generic programming template<typename ContainerT> void info(const ContainerT& c) { typename ContainerT::value_type T; std::cout << "ContainerT is `" << typeid(decltype(c)).name() << "`\n" "value_type is `" << typeid(T).name() << "`\n"; } // type alias used to simplify the syntax of std::enable_if template<typename T> using Invoke = typename T::type; template<typename Condition> using EnableIf = Invoke<std::enable_if<Condition::value>>; template<typename T, typename = EnableIf<std::is_polymorphic<T>>> int fpoly_only(T) { return 1; } struct S { virtual ~S() {} }; int main() { Container<int> c; info(c); // Container::value_type will be int in this function // fpoly_only(c); // error: enable_if prohibits this S s; fpoly_only(s); // okay: enable_if allows this }
Mögliche Ausgabe
ContainerT is `struct Container<int>` value_type is `int`
[bearbeiten] Defect reports
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 1558 | C++11 | ob ungenutzte Argumente in einer Alias-Spezialisierung an der Ersetzung teilnehmen, war nicht spezifiziert |
substitution wird durchgeführt |
[bearbeiten] Siehe auch
typedef-Deklaration
|
erstellt ein Synonym für einen Typ |
| Namespace-Alias | erstellt einen Alias für einen vorhandenen Namespace |