C++ #在名称空间中包括到;嵌入;名称空间中的预写内容
简介:这样做安全吗C++ #在名称空间中包括到;嵌入;名称空间中的预写内容,c++,templates,namespaces,C++,Templates,Namespaces,简介:这样做安全吗 namespace Foo { #include "bar" } 在你愉快地说不之前,我想我有一些规则可以让它相当安全 但我不喜欢它们,因为它们要求includer单独包含所需的所有全局范围头。尽管这可能是可以容忍的,但如果我们设想在名称空间中包含只是一种特殊的管理特性的话 总的来说,外部和转发声明在名称空间中不能很好地工作 所以我问你 a) 还有什么别的陷阱 b) 有更好的办法吗 ==一个[[仅标题库]]== 我喜欢写图书馆。[[仅标题库和链接器库]] 例如 为简单
namespace Foo {
#include "bar"
}
在你愉快地说不之前,我想我有一些规则可以让它相当安全
但我不喜欢它们,因为它们要求includer单独包含所需的所有全局范围头。尽管这可能是可以容忍的,但如果我们设想在名称空间中包含只是一种特殊的管理特性的话
总的来说,外部和转发声明在名称空间中不能很好地工作
所以我问你
a) 还有什么别的陷阱
b) 有更好的办法吗
==一个[[仅标题库]]==
我喜欢写图书馆。[[仅标题库和链接器库]]
例如
为简单包装器类型定义有效的模板
<>(不要陷入“你应该使用一些标准库来代替这个,这是一个例外。我不知道Boost还是C++已经把这个标准化了。我一直在使用包装,因为模板被添加到C++中。”
另外,假设它是一个只包含标题的库,它在Valid.hpp中定义,
打印函数
std::字符串到_字符串(常量有效(&v){
std::ostringstream oss;
如果(v.valid()){oss我认为这是不安全的。您将所有包含项都放在名称空间Foo中。。。 想象一下,您的一些包含来自std名称空间的内容……我无法想象会有多么混乱
我不会这么做。头文件不是黑盒。您可以随时查看项目中包含的头文件,看看是否可以安全地将其包含在命名空间块中。或者更好的是,您可以修改头文件本身以添加命名空间块。即使头文件来自第三方库,并且在后续版本中进行了更改e、 你的项目中的标题不会更改。我知道这是一个老问题,但我想给出一个更详细的答案。另外,请给出潜在问题的真实答案 如果您在名称空间中包含一个头,这里有一些可能会出错的地方
::std::other_stuff
,即,期望std
直接位于全局名称空间中。如果您在名称空间中包含标题,则情况不再如此。此内容的名称查找将失败,标题将不再编译。而且它不仅仅是标准标题;我确信在增压头也是如此std::swap
,std::哈希
或std::less
用于它自己的类型。(您可以重载std::swap
,但不能重载std::hash
和std::less
)方法是关闭库特定的命名空间,打开命名空间std
,并将专门化放在那里。除非库的头包含在任意深度嵌套的命名空间中,否则它无法关闭这些命名空间。它试图打开的命名空间std
将不是::std
,而是:您的命名空间tuff::std
,它可能不包含任何要专门化的主模板,即使它包含了,也仍然是错误的#ifndef YOURLIB_LEGACY_THE_HEADER_H
#define YOURLIB_LEGACY_THE_HEADER_H
#include "namespaced/the_header.h"
using namespace yourlib;
#endif
现在,旧代码应该像往常一样工作
对于新代码,技巧是不包括“namespaced/the_header.h”,而是更改项目设置,使include目录指向namespaced子目录而不是库根目录。然后,您可以简单地包括“the_header.h”“并获取名称空间的版本。我将另外问一个问题,关于仅标题库的最佳用户模式。最新问题:名称冲突会发生……安全吗?当然。例如,如果“bar”是一个空文件,那么它肯定是安全的。但是,通常情况下,如果您不安全
Valid.hpp:
#include <iostream>
#include <sstream>
template<typename T>
class Valid {
private:
T value_;
bool valid_
...
};
...
std::string to_string( const Valid<T>& v ) { ...
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
#include <iostream>
#include <sstream>
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
Type var;
namespace Foo {
void bar() {
extern ::Type ::var;;
extern ::Type ::Foo::bar;
extern ::Type::foo ::bar; // see the ambiguity?
};
namespace Foo {
void bar() {
extern int var;
};
namespace A {
void foo() {
// --- here is a reference to gloal scope extreren ...
#ifndef YOURLIB_LEGACY_THE_HEADER_H
#define YOURLIB_LEGACY_THE_HEADER_H
#include "namespaced/the_header.h"
using namespace yourlib;
#endif