Обнаружение пространства имен в переполнении стека

Можно ли определить, в какой точке кода вы находитесь в пространстве имен? В частности, я хочу включить предупреждение, если файл включается в глобальное пространство имен.

4

Решение

Я могу дать вам подсказку, которая генерирует ошибку компиляции, если заголовок не включен в глобальное пространство имен. Если я знаю конструкцию 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

В любом случае — никто не посмеет включить ваш заголовок в пространство имен, отличное от глобального.

2

Другие решения

Хорошая практика в том числе все Заголовки в глобальном пространстве имен. Откройте все необходимые пространства имен в начале файла и закройте их до конца. Другой способ неизбежно приведет к куче проблем.

** Расширение комментария **

Чтобы предотвратить непреднамеренное включение, вы можете сделать что-то вроде этого:

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

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

Вы можете сделать это с небольшим неудобством, связанным с требованием включения второго заголовка в глобальное пространство имен перед первым.

// 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, или же свернуть свой.

1
По вопросам рекламы [email protected]