简而言之:这样做安全吗?
namespace Foo {
#include "bar"
}
在你愉快地拒绝之前,我想我有一些规则可以保证它相当安全。
但我不喜欢它们,因为它们要求包含器单独包含所需的所有全局范围标头。尽管这可能是可以容忍的,但如果我们想象包含在命名空间中只是一个特殊的管理功能。
总的来说,外部声明和前向声明在命名空间内不能很好地工作。
所以我想我是在问
a) 还有什么其他问题
b) 有更好的方法吗
== A [[仅头文件库]] ==
我喜欢写库。 [[仅头文件库和链接器库]]。
E.g.
#include "Valid.hpp"
为简单的包装类型定义了一个 Valid 模板。
(不要陷入“你应该为此使用一些标准库而不是你自己的库。这是一个例子。我不知道 Boost 或 C++ 是否已经对此进行了标准化。自从模板被添加到 C++ 以来,我一直在使用包装器。 )
另外,我们可以说,它是一个仅包含头文件的库,在 Valid.hpp 中定义:
打印功能
std::string to_string( const Valid& v ) {
std::ostringstream oss;
if( v.valid() ) { oss
因为我认为这是正确的做法
我有 Valid.hpp 包含它所依赖的标头:
Valid.hpp:
#include <iostream>
#include <sstream>
template<typename T>
class Valid {
private:
T value_;
bool valid_
...
};
...
std::string to_string( const Valid<T>& v ) { ...
到目前为止,一切都很好。
我可以直接使用 Valid 。
== 名称冲突 - 尝试使用命名空间内的包含来解决 ==
但有时也会发生碰撞。
有时其他人有自己的有效。
命名空间可以拯救你,对吗?但我不想更改所有现有代码以使用命名空间。
所以,我很想在一个有冲突的新项目中做
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
问题:包含的标头不再是独立的。里面定义的所有东西都不放在里面
命名空间 AG:: 包装器。
“修复”并不难。
我们“必须”做的就是包含 Valid.hpp 依赖的所有顶级库。
如果他们有包含守卫,他们将不会被重新包含。
#include <iostream>
#include <sstream>
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
但它不再是独立的。 :-(
更糟糕的是,有时纯标头库包含外部声明和其自身之外的内容的前向声明。
这些声明也被放置在命名空间内。
特别是,如果外部声明位于命名空间中定义的函数内部。
IE。有时我们使用 extern 和前向声明,而不是包含整个头文件。
这些被包含在命名空间中。
问:有更好的办法吗?
==:: 没有这样做==
提示::: 不这样做。至少不是一直如此,在 gcc 4.7.2 中不是。
(Gcc 在这方面的行为随着时间的推移而改变。Gcc 4.1.2 的行为有所不同。)
E.g.
Type var;
namespace Foo {
void bar() {
extern ::Type ::var;;
extern ::Type ::Foo::bar;
extern ::Type::foo ::bar; // see the ambiguity?
};
但这不仅仅是含糊不清。
int var;
namespace Foo {
void bar() {
extern int var;
};
有效 - Foo::bar'svar 等于::var。
但它仅因命名空间之外的声明而起作用。
以下不起作用
标头
整数变量;
程序文件
命名空间 Foo {
无效栏(){
外部 int 变量;
}
}
尽管以下内容确实如此:
标头
整数变量;
程序文件
无效栏(){
外部 int 变量;
}
}
基本上,这意味着
将函数放入命名空间中并不是一个简单的重构。
将命名空间包裹在一段代码周围,
无论是否#include'd,
还不够。
...至少在有外部或前向声明的情况下不会。
即使你
== 反对将包含内容放入命名空间的意见 ==
Stackoverflow 的人们似乎反对将 #includes 放入命名空间中:
E.g. 如何使用命名空间内单独标头中定义的类:
... you should never write a #include inside a namespace. Where "never" means, "unless you're doing something really obscure that I haven't thought of and that justifies it". You want to be able to look at a file, and see what the fully-qualified names are of all the things in it. You can't do that if someone comes along later and sticks an extra namespace on the front by including from inside their namespace. – Steve Jessop Jan 6 '12 at 16:38
总体问题:
有什么办法,从命名空间的深处,
说“现在这里有一些我依赖于外部世界的名称,而不是名称空间内的名称。”?
IE。我希望能够说
namespace A {
void foo() {
// --- here is a reference to gloal scope extreren ...