Пространства имён
Варианты
Действия

Псевдоним типа, псевдоним шаблона (начиная с C++11)

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений(до C++17*)
Спецификатор noexcept(C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype(C++11)
auto(C++11)
alignas(C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr(C++11)
Определяемые пользователем(C++11)
Утилиты
Атрибуты(C++11)
Types
Объявление typedef
Объявление псевдонима типа(C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
Специальные функции-элементы
Шаблоны
Разное
 

Псевдоним типа является именем, ссылающимся на ранее определённый тип (наподобие typedef)

Псевдоним шаблона является именем, ссылающимся на семейство типов.

Содержание

[править]Синтаксис

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

usingидентификаторатрибуты (необязательно)=идентификатор-типа; (1)
template<список-параметров-шаблона>

usingидентификаторатрибуты (необязательно)=идентификатор-типа;

(2)
атрибуты(C++11) необязательная последовательность любого количества атрибутов
идентификатор имя, вводимое этим объявлением, которое может быть как именем типа (1) так и именем шаблона (2)
список-параметров-шаблонасписок параметров шаблона, как и в объявлении шаблона
идентификатор-типа абстрактный описатель, либо любой другой допустимый идентификатор-типа (который может вводить новый тип, как указано в описании идентификатора-типа). идентификатор-типа не может ссылаться на идентификатор, ни прямо, ни косвенно. Обратите внимание, что точка объявления идентификатора находится на месте точки с запятой, следующей за идентификатором-типа.

[править]Разъяснение

1) Объявление псевдонима типа вводит имя, которое может использоваться в качестве синонима типа, обзначенного идентификатором-типа. Оно не вводит новый тип и не может изменить значение существующего имени типа. Между псевдонимом типа и объявлением typedef нет никакой разницы. Это объявление может появиться в области видимости блока, области видимости класса или области видимости пространства имён.
2) Псевдоним шаблона является шаблоном, который, при специализации, эквивалентен результату подстановки шаблонных аргументов псевдонима шаблона на место параметров шаблона в идентификаторе-типа
template<class T>struct Alloc {};template<class T>using Vec = vector<T, Alloc<T>>;// идентификатор-типа является vector<T, Alloc<T>> Vec<int> v;// Vec<int> означает тоже самое, что и vector<int, Alloc<int>>

Если результат специализации псевдонима шаблона зависит от идентификатора-шаблона, последующие подстановки применяются к этому идентификатору-шаблона:

template<typename...>using void_t =void;template<typename T> void_t<typename T::foo> f(); f<int>();// ошибка, int не имеет вложенного типа foo
(начиная с C++17)

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

template<class T>struct A;template<class T>using B =typename A<T>::U;// идентификатор-типа здесь равен A<T>::Utemplate<class T>struct A {typedef B<T> U;}; B<short> b;// ошибка: B<short> использует свой собственный тип через A<short>::U

Псевдонимы шаблонов никогда не выводятся механизмом вывода шаблонных аргументов при выводе шаблонных шаблонных параметров.

Псевдоним шаблона невозможно специализировать частично или явно.

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

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

template<class T>using A = decltype([]{});// A<int> и A<char> относятся к разным типам замыкания
(начиная с C++20)

[править]Примечание

Макрос Тестирования функциональностиЗначениеСтандартФункциональность
__cpp_alias_templates200704L(C++11)Шаблоны псевдонимов

[править]Пример

#include <iostream>#include <string>#include <type_traits>#include <typeinfo>   // псевдоним типа, полностью эквивалентный// typedef std::ios_base::fmtflags flags;using flags =std::ios_base::fmtflags;// имя 'flags' теперь обозначает тип: flags fl =std::ios_base::dec;   // псевдоним типа, полностью эквивалентный// typedef void (*func)(int, int);using func =void(*)(int,int);// имя 'func' теперь обозначает указатель на функцию:void example(int, int){} func fn = example;   // псевдоним шаблонаtemplate<class T>using ptr = T*;// имя 'ptr<T>' теперь является псевдонимом для указателя на T ptr<int> x;   // псевдоним типа используется для сокрытия шаблонного параметраtemplate<class CharT>using mystring =std::basic_string<CharT,std::char_traits<CharT>>; mystring<char> str;   // псевдоним типа может ввести элемент имени типаtemplate<typename T>struct Container {using value_type = T;};// который может использоваться в обобщённом программированииtemplate<typename ContainerT>void info(const ContainerT& c){typename ContainerT::value_type T;std::cout<<"ContainerT равно `"<<typeid(decltype(c)).name()<<"`\n""value_type равно `"<<typeid(T).name()<<"`\n";}   // псевдоним типа используется для упрощения синтаксиса std::enable_iftemplate<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){return1;}   struct S {virtual ~S(){}};int main(){ Container<int> c; info(c);// Container::value_type в этой функции будет равен int// fpoly_only(c); // ошибка, enable_if такое запрещает S s; fpoly_only(s);// всё в порядке, enable_if такое позволяет}

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

ContainerT равно `struct Container<int>` value_type равно `int`

[править]Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

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

[править]Смотрите также

объявление typedef создаёт синоним для типа[править]
псевдоним пространства имён создаёт псевдоним существующего пространства имён[править]
close