如果在命名空间内创建了类型,我该怎么知道?

时间:2012-05-20 09:54:04

标签: c++ macros typetraits

我创建了Tag系统,它允许ma引擎中的标签实体。它基于c ++类型工作,所以每个标签都是一种类型(我有我的理由)。

现在,当我想创建新标记时,我必须调用struct tagname{};

如果我想在其他文件中使用标记,我使用前向声明struct name;

为了使用户更友好,我创建了宏

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

但是当用户在命名空间和其他外部命名空间中调用一个宏时,我遇到了问题,因为这是两种不同的类型。

我想确保用户在任何命名空间之外调用宏。由于我们的项目位于一个名称空间namespace root中,因此我可以将其用于chcecking。

这是我到目前为止所提出的:

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,我可以使用一些类型特征,但我找不到任何合适的特征。

2 个答案:

答案 0 :(得分:0)

您可以尝试这样的事情:

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

你可能会遇到一个编译器错误,即使在滥用的情况下也不是静态断言,但它应该能够解决问题。你可以通过一个更精细的特质类使它更加用户友好。

答案 1 :(得分:0)

所以看起来

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,"");  }

是答案......

在我接受之前,我会等几天。我仍然对你的答案持开放态度