EMCPP条款9:优先选用别名声明,而非typedef

YiQi 管理员
1
2
typedef std::unique_ptr<std::unordered_map<std::string, std::string>> UPtrMapSS;
using UPtrMapSS = std::unique_ptr<std::unordered_map<std::string, std::string>>;

上面两种的效果是一样的。在处理函数指针的型别时,别名声明好像更容易理解:

1
2
3
4
// FP is a synonym for a pointer to a function taking an int and
// a const std::string& and returning nothing
typedef void (*FP)(int, const std::string&); // typedef same meaning as above
using FP = void (*)(int, const std::string&); // alias declaration

别名声明可以模板化,这种情况下它们被称为别名模板,alias template

1
2
3
4
template<typename T> 
using MyAllocList = std::list<T, MyAlloc<T>>;
// MyAllocList<T> is synonym for std::list<T, MyAlloc<T>>
MyAllocList<Widget> lw; // client code

如果使用 typedef

1
2
3
4
5
template<typename T> 
struct MyAllocList {
typedef std::list<T, MyAlloc<T>> type;
};
MyAllocList<Widget>::type lw; // client code

如果你想在模板内使用 typedef 来创建一个链表,它容纳的对象型别由模板形参指定的话,那你就要给 typedef 的名字加一个 typename 前缀:

1
2
3
4
5
6
template<typename T>
class Widget {
// Widget<T> contains a MyAllocList<T> as a data member
private:
typename MyAllocList<T>::type list;
};

如果 MyAlloclist 是使用别名模板来定义的,那么要写 typename 的要求就消失了

1
2
3
4
5
6
7
8
template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>; // as before

template<typename T>
class Widget {
private:
MyAllocList<T> list;
};

从模板型别形参出发来创建其修正型别:每个C++11中的变换 std::transformation<T>::type,都有一个C++14中名为 std::transformation_t 的对应别名模板。

1
2
3
4
5
6
std::remove_const<T>::type // C++11: const T → T
std::remove_const_t<T> // C++14 equivalent
std::remove_reference<T>::type // C++11: T&/T&& → T
std::remove_reference_t<T> // C++14 equivalent
std::add_lvalue_reference<T>::type // C++11: T → T&
std::add_lvalue_reference_t<T> // C++14 equivalent

要点速记

  • typedef 不支持模板化,但别名声明支持。
  • 别名模板可以让人免写 ::type 后缀,并且在模板内,对于内嵌 typedef 的引用经常要求加上 typename 前缀。
此页目录
EMCPP条款9:优先选用别名声明,而非typedef