Type alias, alias template (since C++11)
Псевдоним типа — это имя, которое ссылается на ранее определённый тип (аналогично
typedef
).
Шаблон псевдонима - это имя, которое ссылается на семейство типов.
Содержание |
Синтаксис
Объявления псевдонимов являются объявлениями со следующим синтаксисом:
using
identifier
attr
(необязательно)
=
type-id
;
|
(1) | ||||||||
template
<
template-parameter-list
>
|
(2) | ||||||||
template
<
template-parameter-list
>
requires
constraint
|
(3) | (начиная с C++20) | |||||||
| attr | - | опциональная последовательность любого количества атрибутов |
| identifier | - | имя, вводимое этим объявлением, которое становится либо именем типа (1) либо именем шаблона (2) |
| template-parameter-list | - | список параметров шаблона , как в объявлении шаблона |
| constraint | - | выражение ограничения (constraint expression) , которое ограничивает параметры шаблона, принимаемые этим псевдонимом шаблона |
| type-id | - | абстрактный декларатор или любой другой допустимый type-id (который может вводить новый тип, как указано в type-id ). type-id не может прямо или косвенно ссылаться на identifier . Обратите внимание, что точка объявления идентификатора находится на точке с запятой после 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) | Псевдонимы шаблонов |
Ключевые слова
Пример
#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 | создает псевдоним существующего пространства имен |