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
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.
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 inside namespace 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:
// Foo.h
// includes go here
namespace project_namespace {
class Foo { ... }
}
// Foo.cpp
// includes go here
namespace project_namespace {
// Foo implementation goes here
}
... 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 a namespace
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 ...