- alias declaration 和
typedef
做的事情完全相同,并且有充分理由使用前者替代后者。 - 为了引入,作者开了个玩笑:如果你要用一个类型
std::unique_ptr<std::unordered_map<std::string, std::string>>
,你绝对不想把它写两次。想想都觉得要增加得腕管综合征(俗称:鼠标手)的风险。 - C++11中 alias declaration 的语法为:
using UPtrMapSS =
std::unique_ptr<std::unordered_map<std::string, std::string>>;
- alias declaration 的主要优势在于模板。它可以被模板化而
typedef
不行。在C++98里如果要用 typedef
实现模板则需要用内嵌在结构体中的 hack 方法。例如,我们要定义使用一个自定义的空间分配器 MyAlloc<T>
的 STL 容器链表(list
)的别名:
template<typename T>
class MyAlloc {
template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>;
MyAllocList<Widget> lw1;
template<typename T>
struct MyAllocList
{
typedef std::list<T, MyAlloc<T>> type;
};
MyAllocList<Widget>::type lw2;
- 如果模板化的
typedef
的类型要在另一个模板中使用,情况会变得更糟。例如我们要在下面这个类中声明一个成员变量:
template<typename T>
class TemplatedClass {
public:
typename MyAllocList<T>::type list;
};
MyAllocList<T>::type
的类型取决于 T
,是一个 dependent type,编译器没理由确信它就一定会是个类型名。C++规定这种情况下要用关键字 typename
来声明其的确是类型。于是,typedef
的解决方案相比 alias declaration 平白多出了两部分:typename
和 ::type
。- 作者提到C++11标准库中存在有关该条款的历史遗留问题。例如,在模板元编程时有时需要对类型
T
去除 const
或 &
标识符。C++11提供的实现居然就是用上述 typedef
+ 结构体的hack方法,直到C++14才提供了 alias declaration 的版本,导致现在标准库中存在两份功能一样的方法(而且完全没有理由不用后者而用前者):
const int a = 0;
std::remove_const<decltype(a)>::type b = a;
std::remove_const_t<decltype(a)> c = a;
cout << type_id_with_cvr<decltype(a)>().pretty_name() << endl;
cout << type_id_with_cvr<decltype(b)>().pretty_name() << endl;
cout << (type_id_with_cvr<decltype(b)>() == type_id_with_cvr<decltype(c)>()) << endl;
- 实际上标准库中后者就是对前者的别名:
总结
typedef
不支持模板化,而 alias declaration 支持。- alias declaration 方法避免了
typedef
通常要用的 typename
前缀和 ::type
后缀。 - C++14提供C++11中所有 type traits 变换的 alias declaration 版本。