Псевдоним типа, псевдоним шаблона (начиная с C++11)
Материал из cppreference.com
Псевдоним типа является именем, ссылающимся на ранее определённый тип (наподобие typedef)
Псевдоним шаблона является именем, ссылающимся на семейство типов.
Содержание |
[править] Синтаксис
Объявления псевдонимов являются объявлениями блока со следующим синтаксисом
using идентификатор атрибуты(необязательно) = ИД-типа ;
|
(1) | ||||||||
template < список-параметров-шаблона >
|
(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>::U template <class T> struct A { typedef B<T> U; }; B<short> b; // ошибка: B<short> использует свой собственный тип через A<short>::U
Псевдонимы шаблонов никогда не выводятся механизмом вывода шаблонных аргументов при выводе шаблонных шаблонных параметров.
Псевдоним шаблона невозможно специализировать частично или явно.[править] Пример
Запустить этот код
#include <string> #include <ios> #include <type_traits> // псевдоним типа, полностью эквивалентный // 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 Container> void fn2(const Container& c) { typename Container::value_type n; } // псевдоним типа используется для упрощения синтаксиса 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 t) { return 1; } struct S { virtual ~S() {} }; int main() { Container<int> c; fn2(c); // Container::value_type в этой функции будет равен int // fpoly_only(c); // ошибка, enable_if такое запрещает S s; fpoly_only(s); // всё в порядке, enable_if такое позволяет }
[править] Смотрите также
| объявление typedef | создаёт синоним для типа |

