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

问题描述 投票:0回答:1

我正在寻找模板代码来回答问题“T类有成员X吗?”。网络上有一些采用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(测试)”调用时,例如通过不同的包含头文件,就会出现问题。 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

虽然我理解编译器不希望看到模板或变量的两个(虽然相同)定义,但我看不出如何解决问题。包含保护显然无济于事,因为它不是编译器抱怨的头文件。

有任何想法吗?

c++ templates sfinae typetraits
1个回答
0
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.