C ++头文件库避免“使用命名空间”污染

时间:2015-05-23 21:19:51

标签: c++ c++11 namespaces

我有一个只有头文件的C ++库,里面有几个命名空间。

例如,一个头文件可能包含

//header1.h
namespace library{
namespace componentA{
   template<typename T>
   class Someclass{};
}
}

另一个

//header2.h
namespace library{
namespace componentB{
   template<typename T>
   class SomeOtherClass{
       void Foo(const componentA::Someclass<T>& reference);
       void Bar(const componentA::Someclass<T>& reference);
   };
}
}

现在虽然这有效,但是只有一个只有头的库,一次又一次地编写命名空间变得很繁琐,特别是当你涉及多个类和嵌套的命名空间时。

所以我这样做了:

//new header2.h
namespace library{
namespace componentB{

   using namespace componentA;

   template<typename T>
   class SomeOtherClass{
       void Foo(const Someclass<T>& reference);
       void Bar(const Someclass<T>& reference);
       void FooBar(const Someclass<T>& reference);
       void FooWithBar(const Someclass<T>& reference);
   };
}
}

虽然这对于键入来说肯定更方便,但它存在的问题是,现在库的客户端也可以使用Someclass<T>这样的componentB命名空间来使用componentB::Someclass<T>,从而导致模糊的界面和最终是不一致的代码。 例如,客户现在可以使用 componentA,即使它最初是在public void methodName(int x, int y){ x = x+ 40; }

中定义的

有没有办法让速记只能“私下”?

4 个答案:

答案 0 :(得分:3)

如果我理解你的问题,那么答案就是否定的。如果在componentA::命名空间中键入名称之前输入/读取componentA是一个太大的问题(老实说,这将是我的偏好),那么你可以使用短命名空间别名:

namespace library { namespace componentB
{
// ...
namespace ca = componentA;
// ...
void foo(ca::SomeClass<T>);
// ...
} }

在任何情况下,我都不鼓励在头文件中使用指令:它们会导致名称冲突和维护问题。

答案 1 :(得分:2)

namespace library {
  namespace componentAImpl{
    using ::library::componentB;
    // ...
    inline namespace exports{
      struct foo{};
    }
  }
  namespace componentA{
    using namespace library::componentAImpl::exports;
  }
}

用户可以访问componentAImpl,但不应该访问。

同时,在library::componentA中公开了一组干净的符号。

答案 2 :(得分:1)

那么,C ++ 11? Using-declaration将另一个名称空间的成员引入当前名称空间或块作用域。

c

答案 3 :(得分:0)

经过一段时间的思考后,我自己想出了解决方案。不幸的是,这并不简单。

//header1.h
namespace lib_noexport{

namespace library{
namespace componentA{
   template<typename T>
   class Someclass{};
}
}
}
}

using namespace lib_noexport;

然后

//header2.h
namespace lib_noexport{

using library::componentA::Someclass;

namespace library{

    namespace componentB{

       template<typename T>
       class SomeOtherClass{
           void Foo(const Someclass<T>& reference){}
       };
    }
}

}
using namespace lib_noexport;

现在产生以下结果:

library::componentB::SomeOtherClass<int> a; //works as expected
Someclass<int> b; //error
library::componentB::Someclass<int> c; //error
library::componentA::Someclass<int> b; //works

尽管如此,用户可能已经足够愚蠢地使用未记录的lib_noexport ::但是我再也无法帮助她..