- 别名声明(
alias declaration
)和typedef
做的事情完全相同,并且前者完全可以代替后者而存在 - 对于函数别名而言
using
更加容易理解
typedef void (*FP)(int, const std::string&)
// using
using FP = void (*)(int, const std::string&)
- 别名声明(
alias declaration
)更大的优势点在于在于模版,别名声明可以被模板化,但是typedef
不能。考虑一个链表的别名,链表使用自定义的内存分配器,MyAlloc
。使用别名模板,这真是太容易了:
template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>
MyAllocList<Widget> lw;
使用typedef
,你就从头开始
template<typename T>
struct MyAllocList{
typedef std::list<T, MyAlloc<T>> type;
};
MyAllocList<Widget>::type lw;
- 如果模板化的
typedef
的类型要在另外一个模板中使用,情况会变得更糟:
template<typename T>
class TemplatedClass {
public:
// MyAllocList<T>::type list; // 错误!
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
的版本,导致现在标准库中存在两份功能一样的方法(而且完全没有理由不用后者而用前者):
// remove_const 使用typedef
template<typename _Tp>
struct remove_const<_Tp const>
{ typedef _Tp type; };
// 使用using
template<typename _Tp>
using remove_const_t = typename remove_const<_Tp>::type;