在c ++中检测命名空间

时间:2012-09-13 15:52:13

标签: c++ namespaces language-lawyer

是否可以检测在给定的代码点是否在命名空间中?特别是,如果文件包含在全局命名空间中,我想要包含警告。

3 个答案:

答案 0 :(得分:2)

良好做法是在全局命名空间中包含所有标头。在文件开头打开所有需要的命名空间,并在结束前关闭它们。另一种方式将不可避免地导致一堆问题。

** 评论分机 **

为防止意外包含,您可以执行以下操作:

In header:
#ifndef INTERNAL_INCLUDE
#error ...
#endif

When used:
#define INTERNAL_INCLUDE
#include "internal.h"
#undef INTERNAL_INCLUDE

答案 1 :(得分:2)

如果标头未包含在全局命名空间中,我可以给你一个产生编译错误的提示。如果我知道C ++ constructiom肯定会生成编译器警告(其他那个#warning)那么它可以用来代替编译错误。

放入标题:

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];
};

当您的标题包含在某个命名空间中时,您将收到错误。

就像这个例子一样:

namespace Some {

struct TestGlobalNamespace
{
   int test_namespace[AreSame<TestGlobalNamespace, ::TestGlobalNamespace>::VALUE];
};

}

你会得到:

prog.cpp:17: error: size of array ‘test_namespace’ is negative

[UPDATE]

然而,更可能是这种错误:

prog.cpp:17: error: ‘::TestGlobalNamespace’ has not been declared
prog.cpp:17: error: template argument 2 is invalid

无论如何 - 没有人敢把你的标题包含在除全局之外的命名空间中。

答案 2 :(得分:1)

您可以在需要第二个标题的小麻烦的情况下执行此操作,以便在第一个标题之前包含在全局命名空间中。

// 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

如果您破坏这两个规则中的任何一个,这将给出相当友好的错误消息,如果您从非全局命名空间中包含stuff_guard.h,则会产生一些不太友好的错误。

如果您遇到旧的编译器并且static_assert不可用,那么您可以使用BOOST_STATIC_ASSERTroll your own