我们在编写代码的时候经常会使用类型别名,比如定义自己的内置类型(跨平台)或者为了简化某种很长的类型。在C++ 98时代我们会使用typedef来完成这个工作。
typedef std::unique_ptr<std::unordered_map<std::string, std::string>> UPtrMapSS;
C++11以后增加了别名声明,它使用using关键字。
using UPtrMapSS = std::unique_ptr<std::unordered_map<std::string, std::string>>;
看上去使用using声明比typedef更容易理解。
typedef void (*FP)(int, const std::string&);
using FP = void (*)(int, const std::string&);
using比typedef的优势体现在模板编程上。
template<typename T>
using MyAllocList = std::list<T, MyAlloc<T>>;
//MyAllocList<T>是std::list<T, MyAlloc<T>>的别名
MyAllocList<Wideget> lw;
如果使用typedef则要麻烦很多。
template<tempname T>
struct MyAllocList {
typedef std::list<T, MyAlloc<T>> type;
}
MyAllocList<Widget>::type lw;
如果使用typedef来定义型别,编译器可能无法判断这个别名到底是个型别还是一个成员变量,我们需要加上typename前缀来告诉编译器,这是一个型别,比如:
template<typename T>
class Widget{
typename MyAllocList<T>::type list;
}
class Wine { ... };
template<>
class MyAllocList<Wine> {
private:
enum class WineType
{White, Red, Rose};
WineType type;
}
//MyAllocList<wine>::type是一个成员变量而非型别
type是一个型别还是一个变量,编译器需要根据T的型别进行推导。但是使用using型别声明,编译器可以很明确的知道这个就是一个型别而非变量。
template<typename T>
class Widget {
private:
MyAllocList<T> list;
};
C++11的型别特征转换还是通过typedef实现的,比如:
std::remove_const<T>::type
C++14中则使用了using别名声明,因此可以使用下面的方式做转换。
std::remove_const_t<T>等价于std::remove_const<T>::type
如果你还在使用C++11完全可以自己使用using来定义这个转换以达到c++14的效果。
template<class T>
using remove_const_t = typename remove_const<T>::type;