Reputation: 10546
Is it possible to detect whether at a given point of code you are in a namespace? In particular, I want to include a warning if a file is being including in the global namespace.
Upvotes: 4
Views: 2352
Reputation: 24412
I can give you a hint that generates compilation error if header is not include in global namespace. If I know C++ constructiom which for sure generates compiler warning (other that #warning) then it could be used instead of compilation error.
Put in your header:
template <class A, class B>
struct AreSame { enum { VALUE = -1 }; };
template <class A>
struct AreSame<A,A> { enum { VALUE = 1 }; };
struct TestGlobalNamespace
{
int test_namespace[AreSame<TestGlobalNamespace, ::TestGlobalNamespace>::VALUE];
};
When your header is include in some namespace you'll get an error.
Like in this example:
namespace Some {
struct TestGlobalNamespace
{
int test_namespace[AreSame<TestGlobalNamespace, ::TestGlobalNamespace>::VALUE];
};
}
You'll get:
prog.cpp:17: error: size of array ‘test_namespace’ is negative
[UPDATE]
However the more probably would be this kind of errors:
prog.cpp:17: error: ‘::TestGlobalNamespace’ has not been declared
prog.cpp:17: error: template argument 2 is invalid
Anyway - no one will dare to include your header to namespace other than global.
Upvotes: 2
Reputation: 982
Good practice is including all headers in global namespace. Open all needed namespaces at the beginning of file and close them before end. Another way will inevitably lead to heap of problems.
** Comment extension **
To prevent unintended inclusion, you can do something like this:
In header:
#ifndef INTERNAL_INCLUDE
#error ...
#endif
When used:
#define INTERNAL_INCLUDE
#include "internal.h"
#undef INTERNAL_INCLUDE
Upvotes: 2
Reputation: 254531
You can do this with the small inconvenience of requiring a second header, to be included in the global namespace before the first.
// stuff_guard.h - include from global namespace to guard stuff.h
#ifndef STUFF_GUARD_H
#define STUFF_GUARD_H
typedef char stuff_guard[1];
#endif
// stuff.h - must be included from non-global namespace, after stuff_guard.h
// No include guard - may be included multiple times, in different namespaces.
#ifndef STUFF_GUARD_H
#error stuff_guard.h must be included before stuff.h
#endif
typedef char stuff_guard[2];
static_assert(sizeof (stuff_guard) != sizeof (::stuff_guard),
"stuff.h must not be included from the global namespace");
// Put your stuff here
This will give reasonably friendly error messages if you break either of these two rules, and a somewhat less friendly error if you include stuff_guard.h
from a non-global namespace.
If you're stuck with an old compiler and static_assert
isn't available, then you could use BOOST_STATIC_ASSERT
, or roll your own.
Upvotes: 1