Как я могу узнать, создан ли тип внутри пространства имен?

Я создал систему тегов, которая позволяет использовать теги в движке ma. Он работает на основе типов C ++, поэтому каждый тег является типом (у меня есть причины).

Теперь, когда я хочу создать новый тег, мне нужно вызвать struct tagname{};.

Если я хочу использовать тег в других файлах, я использую предварительное объявление struct name;

Чтобы сделать его более удобным для пользователя, я создал макросы

#define CREATE_TAG(name) struct name{};
#define USE_TAG(name)    struct name;

Но когда пользователь вызывает один макрос внутри пространства имен, а другой - вне пространства имен, у меня возникает проблема, потому что это два разных типа.

Я хочу убедиться, что пользователь вызывает макросы вне любого пространства имен. Поскольку наш проект находится в одном пространстве имен namespace root, я могу использовать его для проверки.

Вот что я до сих пор придумал:

namespace root
{
    const unsigned TAGS_CAN_NOT_BE_DEFINED_INSIDE_ANY_NAMESPACE = 1;
};

#define CREATE_TAG(name)    namespace root{  struct name{}; static_assert(root::TAGS_CAN_NOT_BE_DEFINED_INSIDE_ANY_NAMESPACE,"");  }
#define USE_TAG(name)       namespace root{  struct name;   static_assert(root::TAGS_CAN_NOT_BE_DEFINED_INSIDE_ANY_NAMESPACE,"");  }

Теперь, когда макрос используется вне корневого пространства имен, все в порядке. При вызове внутри корневого пространства имен или других вложенных пространств имен выдает ошибку TAGS_CAN_BE... not a member.

Но мне это не очень нравится. Мне не нравится вся эта макроэкономика, но вопрос не в этом. Вопрос: есть ли лучший способ узнать, вызывается ли макрос в пространстве имен? Поскольку мои макросы передаются в Type, я могу использовать несколько типографий, но я не нашел ни одного подходящего.


person relaxxx    schedule 20.05.2012    source источник


Ответы (2)


Вы можете попробовать что-то вроде этого:

#include <type_traits>
#define DECLARE_ME(name) struct tag_##name { static_assert(!std::is_same<tag_##name, ::tag_##name>::value, "Not in global namespace"); }

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

person Kerrek SB    schedule 20.05.2012
comment
спасибо, но именно из-за этого другого сообщения об ошибке я отказался от использования is_same. Я получаю ... is not a member of global namespace ... поэтому я использовал сумасшедшую переменную TAGS_CAN ... - person relaxxx; 20.05.2012
comment
Понятно. Но сообщение об ошибке появилось бы только в том случае, если бы произошла ошибка, и правильная программа не пострадала бы ... но в любом случае я действительно думаю, что это невозможно сделать. Препроцессор ничего не знает о языке и вообще не взаимодействует с областью видимости - это просто инструмент лексического поиска / замены. Однако возможно, что всю вашу проблему можно было бы лучше решить с помощью другого подхода. - person Kerrek SB; 20.05.2012
comment
Но если подумать, вопрос на самом деле не о макросе и препроцессоре. Речь идет о написании кода, который может определить, написан ли я (код) в пространстве имен. Затем этот код просто превращается в макрос - person relaxxx; 20.05.2012
comment
@relaxxx: Нет, я думаю, вы спрашиваете об этом только потому, что вы уже мысленно привержены своему макросу. Мое личное впечатление здесь таково, что должно быть лучшее решение, которое идет совершенно другим путем и может быть реализовано на C ++ напрямую (или, возможно, только с очень незначительным макросом). - person Kerrek SB; 20.05.2012
comment
Вы, наверное, правы :) Я уверен, что есть решение получше. Но изначально это было сделано с помощью макросов, которые использовались некоторое время (во многих местах), а теперь возникает скрытая проблема (тип в napespace отличается). Поэтому мне нужно сохранить макросы CREATE_TAG и USE_TAG и обеспечить функциональность проверки. Ваше решение хорошее, но оно не дает мне правильного сообщения об ошибке, которое я хотел бы для пользователей - person relaxxx; 20.05.2012

Так выглядит, что

namespace root
{
    const unsigned TAGS_CAN_NOT_BE_DEFINED_INSIDE_ANY_NAMESPACE = 1;
};

#define CREATE_TAG(name)    namespace root{  struct name{}; static_assert(root::TAGS_CAN_NOT_BE_DEFINED_INSIDE_ANY_NAMESPACE,"");  }
#define USE_TAG(name)       namespace root{  struct name;   static_assert(root::TAGS_CAN_NOT_BE_DEFINED_INSIDE_ANY_NAMESPACE,"");  }

это ответ ...

Я подожду несколько дней, прежде чем приму его. Я все еще открыт для ваших ответов

person relaxxx    schedule 21.05.2012