C++ 中using 与 typedef

using 关键字的应用场景

using 关键字在 C++ 中由来已久,使用得也比较多,现代 C++ 进一步扩展了其应用范围,目前 using 可以用在以下场景中:

  1. 命名空间声明
  2. 命名空间成员声明
  3. 类成员声明
  4. 类继承构造
  5. 类型别名与模板别名

其中的 4,5 是现代 C++ 对 using 关键字应用范围的扩展,5 是用来替代 typedef 的。

代码示例 :

#include 
#include 

template  class MagicType {
public:
  T dark;
  U magic;
};
template 
using TrueDarkMagic = MagicType; // using template alias declaration

int main(void) {
  // case 1: namespace declaration
  using namespace std::filesystem;

  // case 2: namespace member declaration
  using std::cout, std::endl;

  // case 3, 4: class member declaration, inherited constructor
  struct B {
    B() : x_{0} {};
    B(int y) : B() { y_ = y; }; // use delegating constructor
    void print() const { cout << '[' << x_ << ", " << y_ << "]
"; };
    void print(bool) const { cout << '{' << x_ << ", " << y_ << "}
"; };
  private:
    int x_;
    int y_;
  };
  // private inheritance
  struct D : private B {
    using B::B;     // case 4: inherited constructor
    using B::print; // case 3: class member declaration
  };
  D d{6};
  d.print();     // [0, 6]
  d.print(true); // {0, 6}

  // case 5: type alias and alias template declaration
  #define Dstring std::string
  typedef std::string Tstring;
  using Ustring = std::string;

  typedef void (*TFP)(int, const std::string &);  // typedef type alias declaration
  using UFP = void (*)(int, const std::string &); // using type alias declaration

  TrueDarkMagic tdm; // using template alias declaration

  return 0;
}
/

注意上面的代码还用到了现代 C++ 的 委托构造与继承构造 新特性

using 与 typedef

现代 C++ 扩展了 using 关键字的语义,其中就包含了对 typedef 的替换,那 C++ 在设计上为啥不直接扩展 typedef 呢?这个是为了兼容 C,谁也不能保证将来 C 会不会扩展 typedef。因此,在 C++ 编程中推荐无脑的使用 using 关键字,遇到使用 typedef 的老代码也要能看得懂,知道怎么使用 using 来改善。

#include 

template  class MagicType {
public:
  T dark;
  U magic;
};

template  struct TrueDarkMagic0 {
  typedef MagicType type; // typedef
};

template 
using TrueDarkMagic1 = typename TrueDarkMagic0::type; // using with typename

template  using TrueDarkMagic2 = MagicType; // using

#if 0
template 
typedef MagicType TrueDarkMagic3; // not compiles
#endif

int main(void) {
  using std::cout, std::is_same_v;
  cout.setf(std::ios_base::boolalpha);

  // case 1: using is more clear than typedef
  typedef void (*TFP)(int, const std::string &);  // typedef
  using UFP = void (*)(int, const std::string &); // using

  // case 2: alias template declaration
  TrueDarkMagic0::type tdm0;
  TrueDarkMagic1 tdm1;
  TrueDarkMagic2 tdm2;
  cout << is_same_v << '
'; // true
  cout << is_same_v << '
'; // true

  // case 3: C++ type_traits also use using prefer to typedef
  // template  using remove_const_t = typename remove_const<_Tp>::type;
  const int x0 = 1;
  const int y0 = 1;
  std::remove_const::type x00 = 1;
  std::remove_const_t y00 = 1;
  cout << is_same_v << '
'; // true
  cout << is_same_v << '
'; // true

  return 0;
}
/

'using' 用起来确实要比 'typedef' 要方便,标准库也在大量使用 'using' 来改善老的 'typedef' 设计

总结

  1. typedef 不能直接定义模板别名,需要定义额外的模板类来支持
  2. using 是更好的 typedef,推荐使用 using 来改善老的 typedef 设计
  3. 也要注意 using 的其它应用特性

你可能感兴趣的