Spec-Zone.ru › C++

Тип псевдонима, шаблон псевдонима (с C++11)

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

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

Синтаксис

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

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

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

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

Объяснение

1) Объявление типа псевдонима вводит имя, которое можно использовать как синоним для типа, обозначенного тип-идентификатором. Оно не вводит новый тип и не может изменить значение существующего имени типа. Нет разницы между объявлением типа псевдонима и объявлением typedef. Это объявление может появляться в области блока, области класса или области именованного пространства.
2) Шаблон псевдонима — это шаблон, который при специализации эквивалентен результату подстановки аргументов шаблона шаблона псевдонима для параметров шаблона в тип-идентификатор.
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<class T>
using A = decltype([] {}); // A<int> and A<char> refer to different closure types
(с C++20)

Примечания

Макрос проверки функции Значение Std Функция
__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 объявление создаёт синоним для типа
псевдоним пространства имён создаёт псевдоним существующего пространства имён

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/type_alias

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API