“类T是否有成员X”:类模板已经定义

时间:2019-03-10 09:58:16

标签: c++ templates sfinae typetraits

我正在搜索回答以下问题的模板代码:“类T是否有成员X?”。 Web上有一些使用SFINAE的解决方案(例如,请参见How to detect whether there is a specific member variable in class?),但是它们都有缺点,即成员名X在解决方案中是硬编码的。因此,我创建了一个宏DECL_HAS_MEMBER(member_name),该宏声明了检查成员“ member_name”所需的模板类:

#define DECL_HAS_MEMBER(member_name) \
template<typename T, typename = void> struct has_member_##member_name : std::false_type {}; \
template<typename T> \
struct has_member_##member_name<T, decltype((void)T::member_name, (void)0)> : std::true_type {}; \
template<typename T> constexpr auto has_member_##member_name##_v = has_member_##member_name<T>::value;

现在我可以使用以下代码:

DECL_HAS_MEMBER(test)
...
bool has_test = has_member_test_v<MYCLASS>;

(附带说明:实际上,我对代码进行了一些改进,以了解“ test”是否为静态整数数据成员。)

当我在同一个翻译单元中有两个“ DECL_HAS_MEMBER(test)”调用时,例如通过不同的包含的头文件,就会出现问题。 MSVC编译器发出以下错误消息:

warning C4348: 'has_member_test': redefinition of default parameter: parameter 2
error C2953: 'has_member_test': class template has already been defined
error C2976: 'has_member_test': too few template arguments
error C2086: 'const auto has_member_test_v': redefinition

虽然我知道编译器不想看到模板或变量的两个(尽管相同)定义,但我看不到如何解决问题。包含后卫显然没有帮助,因为它不是编译器抱怨的头文件。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

当然有几种选择。这是两个:

1)您的宏为“测试”生成的代码当然适用于任何类。因此,您确实只需要一次。您可以在一个额外的包含文件中定义所有DECL_HAS_MEMBER,将其包含在要进行检查并进行检查的位置。

2)您在要测试的类中执行DECL_HAS_MEMBER。在这种情况下,所有检查都在单独的类名称空间中,不会有冲突。