C++编程中的命名空间基本知识讲解

2020-01-06 14:22:31王旭

内联命名空间 (C++ 11)
与普通嵌套命名空间不同,内联命名空间的成员会被视为父命名空间的成员。这一特性使针对重载函数的依赖于参数的查找可以对父命名空间和嵌套内联命名空间中具有重载的函数起作用。它还可让你在内联命名空间中声明的模板的父命名空间中声明专用化。下面的示例演示在默认情况下,外部代码如何绑定到内联命名空间:


//Header.h
#include <string>


namespace Test
{
 namespace old_ns
 {
  std::string Func() { return std::string("Hello from old"); }
 }

 inline namespace new_ns
 {
  std::string Func() { return std::string("Hello from new"); }
 }
}

#include "header.h"
#include <string>
#include <iostream>

int main()
{
 using namespace Test;
 using namespace std;

 string s = Func();
 std::cout << s << std::endl; // "Hello from new"
 return 0;
}

下面的示例演示如何在内联命名空间中声明的模板的父命名空间中声明专用化:


namespace Parent
{
 inline namespace new_ns
 {
   template <typename T>
   struct C
   {
    T member;
   };
 }
  template<>
  class C<int> {};
}

 

可以将内联命名空间用作版本控制机制,以管理对库的公共接口的更改。例如,可以创建单个父命名空间,并将接口的每个版本封装到嵌套在父命名空间内的其自己的命名空间中。保留最新或首选的版本的命名空间限定为内联,并因此以父命名空间的直接成员的形式公开。调用 Parent::Class 的客户端代码将自动绑定到新代码。通过使用指向包含该代码的嵌套命名空间的完全限定路径,选择使用较旧版本的客户端仍可以对其进行访问。
Inline 关键字必须应用到编译单元中命名空间的第一个声明中。
下面的示例演示一个接口的两个版本,每个版本位于一个嵌套命名空间中。通过 v_10 接口对 v_20 命名空间进行了某些修改,且该命名空间被标记为内联。使用新库并调用 Contoso::Funcs::Add 的客户端代码将调用 v_20 版本。尝试调用 Contoso::Funcs::Divide 的代码现在将获取一个编译时错误。如果它们确实需要该函数,则仍可以通过显式调用 Contoso::v_10::Funcs::Divide 访问 v_10 版本。


namespace Contoso
{
 namespace v_10
 {
  template <typename T>
  class Funcs
  {
  public:
   Funcs(void);
   T Add(T a, T b);
   T Subtract(T a, T b);
   T Multiply(T a, T b);
   T Divide(T a, T b);
  };
 }


 inline namespace v_20
 {
  template <typename T>
  class Funcs
  {
  public:
   Funcs(void);
   T Add(T a, T b);
   T Subtract(T a, T b);
   T Multiply(T a, T b);
   std::vector<double> Log(double);
   T Accumulate(std::vector<T> nums);
  };
 }
}