Можно ли определить, в какой точке кода вы находитесь в пространстве имен? В частности, я хочу включить предупреждение, если файл включается в глобальное пространство имен.
Я могу дать вам подсказку, которая генерирует ошибку компиляции, если заголовок не включен в глобальное пространство имен. Если я знаю конструкцию C ++, которая наверняка генерирует предупреждение компилятора (кроме #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
[ОБНОВИТЬ]
Однако, более вероятно, будут ошибки такого рода:
prog.cpp:17: error: ‘::TestGlobalNamespace’ has not been declared
prog.cpp:17: error: template argument 2 is invalid
В любом случае — никто не посмеет включить ваш заголовок в пространство имен, отличное от глобального.
Хорошая практика в том числе все Заголовки в глобальном пространстве имен. Откройте все необходимые пространства имен в начале файла и закройте их до конца. Другой способ неизбежно приведет к куче проблем.
** Расширение комментария **
Чтобы предотвратить непреднамеренное включение, вы можете сделать что-то вроде этого:
In header:
#ifndef INTERNAL_INCLUDE
#error ...
#endif
When used:
#define INTERNAL_INCLUDE
#include "internal.h"#undef INTERNAL_INCLUDE
Вы можете сделать это с небольшим неудобством, связанным с требованием включения второго заголовка в глобальное пространство имен перед первым.
// 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_ASSERT
, или же свернуть свой.