条款9:优先选用别名声明,而非typedef
1 别名声明和typedef
- 类型别名的使用可以减少打字输入,也提高可读性:
typedef std::unique_ptr<std::unordered_map<std::string, std::string>> UPtrMapSS;
- C++11中,提供了别名声明:
using UPtrMapSS = std::unique_ptr<std::unordered_map<std::string, std::string>>;
- 很多人觉得在处理涉及函数指针的类型时,别名声明更容易理解:
// FP是函数指针的别名,该函数接受一个int和一个const std::string&参数,不返回任何值
typedef void (*FP)(int, const std::string&); // typedef
// 和上面的意义一样
using FP = void (*)(int, const std::string&); // 别名声明
- 别名声明可以模板化(别名模板),而typedef不能。
例如,为使用自定义分配器MyAlloc的链表定义一个别名。使用别名模板,这简直就是小菜一碟:
template<typename T> //MyAllocList<T>
using MyAllocList = std::list<T, MyAlloc<T>>; //是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创建一个链表类型,链表元素类型为模板的类型参数,则必须在typedef名称之前加上typename:
template<typename T>
class Widget {
private: typename MyAllocList<T>::type list; …
}
//MyAllocList<T>::type依赖于模板类型参数(T)的类型
如果MyAllocList被定义为一个别名模板,那么typename和::type就不再需要了:
template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>; // 和以前一样
template<typename T>
class Widget {
private:MyAllocList<T> list; // 没有 “typename” 和 "::type"…
};
- 有时对于某种类型 T,希望去掉 T 中包含的const或引用限定符,C++11 为你提供了执行这些类型转换的工具。
std::remove_const<T>::type // 从 const T 创建 T
std::remove_reference<T>::type // 从 T& and T&& 创建 T
std::add_lvalue_reference<T>::type // 从 T 创建 T& //C++ 11的类型特征是通过模板化结构体中的嵌套typedef实现的,需要使用typename前缀
对应的c++ 14别名模板std::transformation_t:
std::remove_const<T>::type // C++11: const T → T
std::remove_const_t<T> // C++14 的等效代码
std::remove_reference<T>::type // C++11: T&/T&& → T
std::remove_reference_t<T> // C++14 的等效代码
std::add_lvalue_reference<T>::type // C++11: T → T&
std::add_lvalue_reference_t<T> // C++14 的等效代码
即使没有C++ 14,自己编写别名模板也是小菜一碟:
template <class T>
using remove_const_t = typename remove_const<T>::type;
template <class T>
using remove_reference_t = typename remove_reference<T>::type;
template <class T>
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
2 要点速记
- typedef不支持模板化,但别名声明支持。
- 别名模板避免使用“::type”后缀,以及在模板中的“typename”前缀(typedef所需要的)。
- C++ 14为所有的C++ 11类型特征转换提供了别名模板。