Namespaces
Variants

Type alias, alias template (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

L'alias de type est un nom qui fait référence à un type précédemment défini (similaire à typedef ).

L'alias de modèle est un nom qui fait référence à une famille de types.

Table des matières

Syntaxe

Les déclarations d'alias sont des déclarations avec la syntaxe suivante :

using identifiant attr  (optionnel) = type-id ; (1)
template < template-parameter-list >

using identifiant attr  (optionnel) = type-id ;

(2)
template < template-parameter-list > requires constraint

using identifiant attr  (optionnel) = type-id ;

(3) (depuis C++20)
attr - séquence facultative d'un nombre quelconque d' attributs
identifier - le nom introduit par cette déclaration, qui devient soit un nom de type (1) soit un nom de template (2)
template-parameter-list - liste de paramètres de template , comme dans la déclaration de template
constraint - une expression de contrainte qui restreint les paramètres de template acceptés par ce template d'alias
type-id - déclarateur abstrait ou tout autre type-id valide (qui peut introduire un nouveau type, comme indiqué dans type-id ). Le type-id ne peut pas faire référence directement ou indirectement à identifier . Notez que le point de déclaration de l'identifiant se situe au point-virgule suivant type-id .

Explication

1) Une déclaration d'alias de type introduit un nom qui peut être utilisé comme synonyme du type désigné par type-id . Elle n'introduit pas un nouveau type et ne peut pas modifier la signification d'un nom de type existant. Il n'y a aucune différence entre une déclaration d'alias de type et une déclaration typedef . Cette déclaration peut apparaître dans la portée d'un bloc, la portée d'une classe ou la portée d'un espace de noms.
2) Un alias template est un template qui, lorsqu'il est spécialisé, est équivalent au résultat de la substitution des arguments du template pour les paramètres du template dans le type-id .
template<class T>
struct Alloc {};
template<class T>
using Vec = vector<T, Alloc<T>>; // type-id est vector<T, Alloc<T>>
Vec<int> v; // Vec<int> est identique à vector<int, Alloc<int>>

Lorsque le résultat de la spécialisation d'un alias template est un template-id dépendant, les substitutions ultérieures s'appliquent à ce template-id :

template<typename...>
using void_t = void;
template<typename T>
void_t<typename T::foo> f();
f<int>(); // erreur, int n'a pas de type imbriqué foo

Le type produit lors de la spécialisation d'un alias template ne peut pas utiliser directement ou indirectement son propre type :

template<class T>
struct A;
template<class T>
using B = typename A<T>::U; // type-id est A<T>::U
template<class T>
struct A { typedef B<T> U; };
B<short> b; // erreur : B<short> utilise son propre type via A<short>::U

Les alias templates ne sont jamais déduits par la déduction d'argument de template lors de la déduction d'un paramètre template template.

Il n'est pas possible de partiellement ou explicitement spécialiser un alias template.

Comme toute déclaration de template, un alias template ne peut être déclaré qu'au niveau de la portée de classe ou de la portée de namespace.

Le type d'une expression lambda apparaissant dans une déclaration de template d'alias est différent entre les instanciations de ce template, même lorsque l'expression lambda n'est pas dépendante.

template<class T>
using A = decltype([] {}); // A<int> and A<char> refer to different closure types
(depuis C++20)

Notes

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_alias_templates 200704L (C++11) Alias templates

Mots-clés

using

Exemple

#include <iostream>
#include <string>
#include <type_traits>
#include <typeinfo>
// alias de type, identique à
// typedef std::ios_base::fmtflags flags;
using flags = std::ios_base::fmtflags;
// le nom 'flags' désigne maintenant un type :
flags fl = std::ios_base::dec;
// alias de type, identique à
// typedef void (*func)(int, int);
using func = void (*) (int, int);
// le nom 'func' désigne maintenant un pointeur vers une fonction :
void example(int, int) {}
func f = example;
// alias de modèle
template<class T>
using ptr = T*;
// le nom 'ptr<T>' est maintenant un alias pour pointeur vers T
ptr<int> x;
// alias de type utilisé pour masquer un paramètre de modèle
template<class CharT>
using mystring = std::basic_string<CharT, std::char_traits<CharT>>;
mystring<char> str;
// un alias de type peut introduire un typedef membre
template<typename T>
struct Container { using value_type = T; };
// qui peut être utilisé en programmation générique
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";
}
// alias de type utilisé pour simplifier la syntaxe de 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 sera int dans cette fonction
//  fpoly_only(c); // erreur : enable_if interdit ceci
    S s;
    fpoly_only(s); // correct : enable_if autorise ceci
}

Sortie possible :

ContainerT is `struct Container<int>`
value_type is `int`

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR S'applique à Comportement tel que publié Comportement correct
CWG 1558 C++11 la participation des arguments inutilisés dans une spécialisation d'alias
à la substitution n'était pas spécifiée
la substitution
est effectuée

Voir aussi

typedef déclaration crée un synonyme pour un type
alias d'espace de noms crée un alias d'un espace de noms existant