C++仅标头库可避免"using namespace"污染
C++ header-only library avoid "using namespace" pollution
我有一个只有头的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);
};
}
}
虽然这当然更方便键入,但它的问题是,现在库的客户端也可以像这样使用componentB
名称空间来使用Someclass<T>
,这会导致接口不明确,并最终导致代码不一致。例如,客户端现在可以使用componentB::Someclass<T>
,即使它最初是在componentA
中定义的
有没有办法让速记只能"私下"使用?
namespace library {
namespace componentAImpl{
using ::library::componentB;
// ...
inline namespace exports{
struct foo{};
}
}
namespace componentA{
using namespace library::componentAImpl::exports;
}
}
用户可以访问componentAImpl
,但不应该访问。
同时,在library::componentA
中暴露了一组干净的符号。
如果我正确理解你的问题,那么答案是否定的。如果在从componentA
名称空间键入名称之前键入/读取componentA::
太麻烦了(老实说,这是我的偏好(,那么你可以使用短名称空间别名:
namespace library { namespace componentB
{
// ...
namespace ca = componentA;
// ...
void foo(ca::SomeClass<T>);
// ...
} }
无论如何,我都不鼓励在头文件中使用指令:它们会导致名称冲突和维护问题。
好吧,C++11?使用声明将另一个命名空间的成员引入当前命名空间或块范围。
namespace library{
namespace componentB{
using componentA::SomeOtherClass;
template<typename T>
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);
};
}
}
经过一段时间的思考,我自己找到了解决方案。不幸的是,这并不简单。
//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::,但我再也帮不了她了。。
相关文章:
- "using namespace std;"在C++的作用是什么?
- 为什么我需要做'using namespace std'而不是"使用 std::cout"?
- 'using namespace'实现细节的便捷方法(仅标头库)?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- "using namespace"子句在什么范围内有效?
- 如何找到"using namespace std"的违规用法?
- 在实现文件中,我们应该更喜欢"using namespace"指令还是将实现包装在命名空间 { } 中?
- 如何根据对象名称将'using namespace'添加到类定义中?
- 没有任何 #include "using namespace std;"?
- 用于定义全局函数"using namespace"
- 'using namespace'如何在C++运作
- 为什么我们应该在使用"using namespace std"时使用"#include<iostream>"?
- 如何在代码中使用 STD 而不包含"using namespace std"?
- 如何正确使用"using namespace foo?"
- 使用不带前缀"std"且不带"using namespace std;"的 std::sort() 成功编译
- 总是"using namespace std" ?
- 头文件中可以包含"using namespace"语句吗?
- 为什么以及如何"using namespace"声明会混淆C++中的编译器?
- "using namespace std;"是否免于过多代码规则?
- C++如何知道在哪里查找使用 "using namespace ..." 指定的命名空间?