声明别名和typedef


  • 声明别名

    C++11 提供声明别名alias declarations

      using UptrMapSS = std::unique_ptr<std::unordered_map<std::string, std::string>>;
    

    看到这段代码就想到了C++98的实现:

      typedef std::unique_ptr<std::unordered_map<std::string, std::string>> UPtrMapSS;
    

    再举例:

      //C++98的函数指针类型定义
      typedef void (*FP)(int, const std::string&);
    
      // 声明别名
      using FP = void (*)(int, const std::string&);
    

  • 比较

    声明别名支持模板化,而typedef不支持:

      template<typname T> 
      using MyAllocList = std::list<T, MyAlloc<T>>;
    
      MyAllocList<Person> lp1;
    
      template<typename T>
      struct MyAllocList 
      { 
          typedef std::list<T, MyAlloc<T>> type;
      }; 
    
      MyAllocList<Person>::type lp2;
    

    声明别名跳过了typename而typedef不行,例如你想在一个模板类中使用typedef定义的类型名,则必须在这个typedef名称前使用typename:

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

    MyAllocList::type 表示一个依赖于模板类型参数 T 的类型,因此 MyAllocList::type 是一个依赖类型( dependent type )而使用声明别名则不需要增加typename:

      template<typname T> 
      using MyAllocList = std::list<T, MyAlloc<T>>;
    
      template<typename T>
      class Person
      {
      private:
          MyAllocList<T> list;
      }
    

    当使用声明别名时编译器认为它是一个类型名称,而使用typedef时必须使用typename是因为MyAllocList::type有可能是一个变量


  • C++11与C++14在类型特征转换这两方面的差异

    目前C++11提供的类型特征转换工具还是以typedef的形式,C++14开始在typedef的基础上使用声明别名

    C++11:

      std::remove_const<T>::type
      std::remove_reference<T>::type
      std::add_lvalue_reference<T>::type 
    

    C++14:

      std::remove_const<T>::type
      std::remove_const_t<T> 
    
      std::remove_reference<T>::type
      std::remove_reference_t<T>
    
      std::add_lvalue_reference<T>::type
      std::add_lvalue_reference_t<T> 
    

    如果你正在使用C++11又想用声明别名,以上面的代码为例在一个自定义的命名空间包装一下:

      template<typename T>
      using remove_const_t = typename std::remove_const<T>::type;
    

  • 最后

    • typedef 不支持模板化,但是别名声明支持

    • 模板别名避免了::type后缀,在模板中,typedef还经常要求使用typename前缀

    • C++14为C++11中的类型特征转换提供了模板别名