类型别名,别名模版 (C++11 起)

来自cppreference.com
< cpp‎ | language

类型别名是指代先前定义类型的名称(同 typedef )。

别名模版是指代一族类型的名称。

目录

[编辑] 语法

别名声明是有下列语法的声明

using identifier attr(可选) = type-id ; (1)
template < template-parameter-list >

using identifier attr(可选) = type-id ;

(2)
attr(C++11) - 可选的任意数量属性的序列
identifier - 此声明引入的名称,它成为类型名 (1) 或模板名 (2)
template-parameter-list - 模板形参列表,同在模板声明
type-id - 抽象声明器或任何合法的 type-id (可以引入新类型,如 type-id 中所标注)。 type-id 不能直接或间接指代 identifier 。注意标识符的声明点在后随 type-id 的分号。

[编辑] 解释

1) 类型别名声明引入能用做 type-id 所指代类型的同意语的名称。它不引入新类型,且不能更改既存类型名的含义。类型别名声明和 typedef 声明直接无区别。此声明可出现于块作用域、类作用域或命名空间作用域。
2) 别名模板是特化时等价于以别名模板实参替换 type-id 中形参的结果。
template<class T>
struct Alloc { };
template<class T>
using Vec = vector<T, Alloc<T>>; // type-id 为<T, Alloc<T>>
Vec<int> v; // Vec<int> 同 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>(); // 错误, int 无嵌套类型 foo
(C++14 起)

特化别名模版时生成的类型不允许直接或间接使用其名:

template<class T>
struct A;
template<class T>
using B = typename A<T>::U; // type-id 为 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 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 Container>
void g(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;
    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 别名模板特化中未使用实参是否参与替换是未指定的 进行替换

[编辑] 参阅

typedef 声明 为类型创建同义词[编辑]