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

Псевдоним типа — это имя, которое ссылается на ранее определённый тип (аналогично typedef ).

Шаблон псевдонима - это имя, которое ссылается на семейство типов.

Содержание

Синтаксис

Объявления псевдонимов являются объявлениями со следующим синтаксисом:

using identifier attr  (необязательно) = type-id ; (1)
template < template-parameter-list >

using identifier attr  (необязательно) = type-id ;

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

using identifier attr  (необязательно) = type-id ;

(3) (начиная с C++20)
attr - опциональная последовательность любого количества атрибутов
identifier - имя, вводимое этим объявлением, которое становится либо именем типа (1) либо именем шаблона (2)
template-parameter-list - список параметров шаблона , как в объявлении шаблона
constraint - выражение ограничения (constraint expression) , которое ограничивает параметры шаблона, принимаемые этим псевдонимом шаблона
type-id - абстрактный декларатор или любой другой допустимый type-id (который может вводить новый тип, как указано в type-id ). type-id не может прямо или косвенно ссылаться на identifier . Обратите внимание, что точка объявления идентификатора находится на точке с запятой после type-id .

Объяснение

1) Объявление псевдонима типа вводит имя, которое может использоваться как синоним для типа, обозначенного type-id . Оно не вводит новый тип и не может изменить значение существующего имени типа. Нет разницы между объявлением псевдонима типа и typedef объявлением. Это объявление может появляться в области видимости блока, области видимости класса или области видимости пространства имен.
2) Шаблонный псевдоним (alias template) — это шаблон, который при специализации эквивалентен результату подстановки аргументов шаблона вместо параметров шаблона в type-id .
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>>

Когда результатом специализации шаблонного псевдонима является зависимый template-id , последующие подстановки применяются к этому template-id:

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

Тип, получаемый при специализации шаблонного псевдонима, не может прямо или косвенно использовать собственный тип:

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

Шаблонные псевдонимы никогда не выводятся через template argument deduction при выводе шаблонного параметра-шаблона.

Невозможно выполнить частичную или явную специализацию шаблонного псевдонима.

Как и любое объявление шаблона, псевдоним шаблона может быть объявлен только в области класса или области пространства имен.

Тип лямбда-выражения в объявлении псевдонима шаблона различается между инстанциациями этого шаблона, даже когда лямбда-выражение не является зависимым.

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

Примечания

Макроопределение для проверки возможности Значение Стандарт Возможность
__cpp_alias_templates 200704L (C++11) Псевдонимы шаблонов

Ключевые слова

using

Пример

#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
}

Возможный вывод:

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

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной спецификации Корректное поведение
CWG 1558 C++11 не было указано, участвуют ли неиспользуемые аргументы в специализации псевдонима
в подстановке
подстановка
выполняется

Смотрите также

typedef declaration создает синоним для типа
namespace alias создает псевдоним существующего пространства имен