拉 C/C++将标准库放入您的项目命名空间中,好主意吗?
我正在移植一些开源代码,以便它可以在另一个 C++ 编译器上构建。似乎不断出现的困难和主题之一是编译器提供的标准库的实现差异。
例如,我正在编译的源文件之一包括
。但是,它给了我以下错误:
Error E2316 g:\Borland\BCC593\Include\sys/types.h 45: 'time_t' is not a member of 'std'
Error E2272 g:\Borland\BCC593\Include\sys/types.h 45: Identifier expected
在查看其根本原因后,我发现该项目的主要包含标头之一是在此模式中包含
:
project_source1.cpp:
#include "../TargetPlatform.h"
#include "project_config.h"
#include <windows.h>
namespace project_namespace {
#include "project_component/all.h"
// more project includes down here
// ...
}
project_component/all.h:
#ifndef INCLUDE_GUARDS
#define INCLUDE_GUARDS
#include <sys/types.h>
#include "project_header1.h"
#include "project_header2.h"
// and other headers etc..
// followed with class definitions and what not.
#endif
这一切都很好,除了一个问题,
是为我要移植到的编译器实现的类似的东西:
精简到本质:
namespace std {
typedef long time_t;
typedef short dev_t;
typedef short ino_t;
typedef short mode_t;
typedef short nlink_t;
typedef int uid_t;
typedef int gid_t;
typedef long off_t;
} // std
using std::time_t;
using std::dev_t;
using std::ino_t;
using std::mode_t;
using std::nlink_t;
using std::uid_t;
using std::gid_t;
using std::off_t;
这就是我看到的编译错误的原因。因为项目包含
在其自己的命名空间中,所以 time_t、off_t、dev_t 等内容被放入范围 project_namespace 中: :std::
这显然不是我们想要的。
处理这个问题的最佳方法是什么?请记住,可能还有以类似方式定义的其他标准库头文件,而不仅仅是 sys/types.h
。是否有任何与此问题相关或半相关的 C++ 习惯用法(或者由于其实现方式而可能与之不一致)?如果是的话,如何才能调和呢?
谢谢
I'm porting some open source code so that it can build on another c++ compiler. One of the difficulties and themes that seem to keep cropping up are implementation differences of the provided standard library by the compiler.
For example, one of the source files that I'm compiling includes <sys/types.h>
. However, it gives me the following errors:
Error E2316 g:\Borland\BCC593\Include\sys/types.h 45: 'time_t' is not a member of 'std'
Error E2272 g:\Borland\BCC593\Include\sys/types.h 45: Identifier expected
After looking at the root cause of this I found that one of the main include headers of the project is including <sys/types.h>
in this pattern:
project_source1.cpp:
#include "../TargetPlatform.h"
#include "project_config.h"
#include <windows.h>
namespace project_namespace {
#include "project_component/all.h"
// more project includes down here
// ...
}
project_component/all.h:
#ifndef INCLUDE_GUARDS
#define INCLUDE_GUARDS
#include <sys/types.h>
#include "project_header1.h"
#include "project_header2.h"
// and other headers etc..
// followed with class definitions and what not.
#endif
This is all well and good except for one problem, the <sys/types.h>
is implemented something like this for the compiler I'm porting to:
<sys/types.h>
trimmed to the essence:
namespace std {
typedef long time_t;
typedef short dev_t;
typedef short ino_t;
typedef short mode_t;
typedef short nlink_t;
typedef int uid_t;
typedef int gid_t;
typedef long off_t;
} // std
using std::time_t;
using std::dev_t;
using std::ino_t;
using std::mode_t;
using std::nlink_t;
using std::uid_t;
using std::gid_t;
using std::off_t;
And this is the cause of the compile error I'm seeing. Because the project is including <sys/types.h>
inside its own namespace, things like time_t, off_t, dev_t etc get put into the scope project_namespace::std::
which is obviously not what's intended.
What's the best way to handle this? Keep in mind there could be other standard library headers defined in a similar fashion and not just sys/types.h
. Are there any C++ idioms that's relevant or semi-related to this issue(or possibly even at odds with it due to the way this is implemented)? If so, how can it be reconciled?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想说您需要更改有问题的代码,以便不再在
project_namespace
中定义标准类型。在我看来,您有两个主要问题:[1]您在
project_all.h
中有一个包罗万象的标头,[2]它在内
。我将首先解决后者。如果您的项目想要将某些内容放入自己的命名空间中,那很好,但应该按如下方式完成:#include
d命名空间project_namespace...换句话说,您的类的标头和实现文件需要说明这些类属于哪个命名空间,“自我命名空间”。所有
#include
都位于命名空间
之外,因为每个类的头文件都声明了该类所属的命名空间。这是标准库使用的约定。现在,如果您仍然想使用
project_all.h
您可以这样做。没有命名空间——因为每个头文件都会将其声明放置在它想要(或不)的命名空间中。但最好不要使用
project_all.h
;相反,#include
单独包含头文件并使依赖关系明确。如果响应是“头文件太多”,这可能表明组件之间存在高度耦合。我意识到这可能不是您想要的答案,抱歉......
I would say you need to change the offending code so that the standard types are no longer defined within
project_namespace
.It seems to me you have two major issues: [1] you have a catch-all header in
project_all.h
and [2] it's#include
d insidenamespace project_namespace
. I'll address the latter first. If your project has things it wants to put in its own namespace, that's fine, but it should be done as follows:... in other words, your classes' header and implementation files need to say what namespace the classes belong in, "self-namespacing" as it were. All your
#include
s are outside anamespace
because the header file for each class declares the namespaces the class belongs to. This is the convention used by the standard library.Now if you still want to use a
project_all.h
you can do so. Without the namespace -- because each header file will place its declarations in the namespace it wants to (or not).But it would be better to dispense with
project_all.h
; instead,#include
the header files individually and make the dependencies explicit. And if the response is "there are too many header files", that's probably a sign of a high degree of coupling between your components.I realize this is probably not the answer you wanted, sorry ...
这是一个坏主意。不要这样做。将命名空间声明放入每个头文件中。命名空间范围内永远不要有
#include
指令。“从不”是一个很强烈的词,在极少数情况下您可能会想要这样做。如果您要
#include
的文件也有#include
指令,那么您几乎肯定不希望这样做,甚至比不这样做更是如此。如果您需要能够轻松地重命名命名空间或根据上下文使用相同的标头在多个不同的命名空间中声明相同的符号,请使用预处理器来更改命名空间名称。这样做非常难看,但比你现在正在做的要好得多。
作为一种快速而肮脏的解决方案,您可以做的一件事是
#include
以及命名空间声明之前包含的任何其他系统标头。这将导致系统头文件中的双重包含保护启动并避免在命名空间内声明内容。This is a bad idea. Do not do things this way. Put the namespace declarations inside each header file. Never have a
#include
directive inside the scope of a namespace.Never is a strong word, and there are very rare cases in which you might want to do this. If the file you're
#include
ing also has#include
directives, you almost certainly do not want to be doing this, even more so than if they didn't.If you need to be able to easily rename your namespace or use the same header to declare the same symbols in several different namespaces depending on context, use the preprocessor to change the namespace name instead. That's extremely ugly to do, but much better than what you're currently doing.
One thing you can do as a quick and dirty solution to this is
#include <sys/types.h>
and any other system header that's included before the namespace declaration. This will cause the double-inclusion guards in the system header files to kick in and avoid declaring stuff inside the namespace.