Search code examples
c++namespacesporting

Pulling C/C++ standard library into your project namespace, good idea?


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


Solution

  • 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 #includeing 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.