Псевдоним типа, шаблон псевдонима (начиная с 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 | - | выражение ограничения, ограничивающее параметры шаблона, допустимые для этого шаблона псевдонима |
| 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<class T>
using A = decltype([] {}); // A<int> and A<char> refer to different closure types
| (начиная с 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 объявление | создаёт синоним типа |
| псевдоним пространства имён | создаёт псевдоним существующего пространства имён |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/type_alias