Type alias, alias template (since C++11)
类型别名是指向先前已定义类型的名称(类似于
typedef
)。
别名模板是一个指代一系列类型的名称。
目录 |
语法
别名声明是具有以下语法的 声明 :
using
标识符
属性
(可选)
=
类型标识
;
|
(1) | ||||||||
template
<
模板形参列表
>
|
(2) | ||||||||
template
<
模板形参列表
>
requires
约束
|
(3) | (自 C++20 起) | |||||||
| attr | - | 可选的任意数量 属性 序列 |
| identifier | - | 此声明引入的名称,将成为类型名 (1) 或模板名 (2) |
| template-parameter-list | - | 模板形参列表 ,与 模板声明 中相同 |
| constraint | - | 约束表达式 ,用于限制此别名模板接受的模板形参 |
| 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<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
在推导模板模板参数时, 模板实参推导 永远不会推导出别名模板。
无法对别名模板进行 部分特化 或 显式特化 。与任何模板声明类似,别名模板只能在类作用域或命名空间作用域中声明。
|
出现在别名模板声明中的 lambda表达式 类型在不同模板实例化中是不同的,即使该lambda表达式不依赖模板参数。 template<class T> using A = decltype([] {}); // A<int> 和 A<char> 引用不同的闭包类型 |
(since C++20) |
注释
| 特性测试宏 | 值 | 标准 | 特性 |
|---|---|---|---|
__cpp_alias_templates
|
200704L
|
(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 f = 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; // 类型别名可以引入成员 typedef 名称 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 is `" << typeid(decltype(c)).name() << "`\n" "value_type is `" << typeid(T).name() << "`\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) { return 1; } 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 is `struct Container<int>` value_type is `int`
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用标准 | 发布时行为 | 正确行为 |
|---|---|---|---|
| CWG 1558 | C++11 |
未说明别名特化中未使用的参数
是否参与替换 |
执行
替换 |
另请参阅
typedef
declaration
|
为类型创建同义词 |
| namespace alias | 创建现有命名空间的别名 |