pythonic metaphor
pythonic metaphor

Reputation: 10546

Detecting namespace in c++

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

Answers (3)

PiotrNycz
PiotrNycz

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

Pavel Ognev
Pavel Ognev

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

Mike Seymour
Mike Seymour

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

Related Questions