类型别名是指代先前定义的类型的名字(与 typedef 类似)。
别名模版是指代一族类型的名字。
语法
别名声明是具有下列语法的声明:
using 标识符 attr(可选) = 类型标识 ; | (1) | |
template < 模板形参列表 > using 标识符 attr(可选) = 类型标识 ; | (2) | |
attr(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>>
当特化别名模板的结果是一个待决的模板标识时,对这个模板标识应用后继的替换:
| (C++14 起) |
特化别名模版时所生成的类型,不允许直接或间接使用其自身类型:
- 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 使用其自身类型
在推导模板模板形参时,模板实参推导始终不推导别名模板。
不可能部分特化或显式特化别名模板。
与任何模板声明相似,别名模版仅可声明于类作用域或命名空间作用域。
出现于别名模版声明中的lambda 表达式的类型,在该模板的不同实例化间不同,即使该 lambda 表达式非待决也是如此。
| (C++20 起) |
示例
运行此代码
- #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 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 ContainerType>
- void g(const ContainerType& c) { typename ContainerType::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;
- g(c); // Container::value_type 将在此函数为 int
- // fpoly_only(c); // 错误:enable_if 禁止它
- S s;
- fpoly_only(s); // OK:enable_if 允许它
- }
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
DR | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
CWG 1558 | C++14 | 别名模板特化中的未使用实参是否参与替换是未指明的 | 进行替换 |
当前内容版权归 cppreference 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 cppreference .