C++ header-only 库避免 "using namespace" 污染
C++ header-only library avoid "using namespace" pollution
我有一个 header-only C++ 库,其中包含多个命名空间。
例如一个 header 文件可能包含
//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);
};
}
}
虽然这可行,但拥有一个 header-only 库,一遍又一遍地编写命名空间变得乏味,尤其是当您涉及多个 类 和嵌套命名空间时。
所以我这样做了:
//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
中定义的
有没有办法让 shorthand 只可用 "privately"?
如果我没有正确理解你的问题,那么答案是否定的。如果 typing/reading componentA::
在 componentA
命名空间的类型名称之前是个大问题(老实说,这是我的偏好),那么您可以使用短命名空间别名:
namespace library { namespace componentB
{
// ...
namespace ca = componentA;
// ...
void foo(ca::SomeClass<T>);
// ...
} }
无论如何,我不鼓励在头文件中使用指令:它们会导致名称冲突和维护问题。
嗯,C++ 11? Using-declaration 将另一个命名空间的成员引入当前命名空间或块范围。
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);
};
}
}
namespace library {
namespace componentAImpl{
using ::library::componentB;
// ...
inline namespace exports{
struct foo{};
}
}
namespace componentA{
using namespace library::componentAImpl::exports;
}
}
用户可以访问 componentAImpl
,但不应该。
与此同时,library::componentA
中公开了一组干净的符号。
经过一段时间的思考,我自己想出了解决方案。不幸的是,这并不简单。
//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:: 但是我再也帮不了她了..
我有一个 header-only C++ 库,其中包含多个命名空间。
例如一个 header 文件可能包含
//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);
};
}
}
虽然这可行,但拥有一个 header-only 库,一遍又一遍地编写命名空间变得乏味,尤其是当您涉及多个 类 和嵌套命名空间时。
所以我这样做了:
//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
有没有办法让 shorthand 只可用 "privately"?
如果我没有正确理解你的问题,那么答案是否定的。如果 typing/reading componentA::
在 componentA
命名空间的类型名称之前是个大问题(老实说,这是我的偏好),那么您可以使用短命名空间别名:
namespace library { namespace componentB
{
// ...
namespace ca = componentA;
// ...
void foo(ca::SomeClass<T>);
// ...
} }
无论如何,我不鼓励在头文件中使用指令:它们会导致名称冲突和维护问题。
嗯,C++ 11? Using-declaration 将另一个命名空间的成员引入当前命名空间或块范围。
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);
};
}
}
namespace library {
namespace componentAImpl{
using ::library::componentB;
// ...
inline namespace exports{
struct foo{};
}
}
namespace componentA{
using namespace library::componentAImpl::exports;
}
}
用户可以访问 componentAImpl
,但不应该。
与此同时,library::componentA
中公开了一组干净的符号。
经过一段时间的思考,我自己想出了解决方案。不幸的是,这并不简单。
//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:: 但是我再也帮不了她了..