检测任意成员的存在

Ros*_*lav 9 c++ templates c++11 c++14

使用以下方法编写将检测类型中特定成员的存在的模板很容易void_t:

#include <type_traits>

// This comes from cppreference
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;

// primary template handles types that have no ::aMember 
template< class T, class = void_t<> >
struct has_aMember : std::false_type { };

// specialization recognizes types that do have a ::aMember
template< class T >
struct has_aMember<T, void_t<decltype( T::aMember )>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)

现在,如果我想检测是否存在其他成员,我将不得不复制粘贴检测器模板,只需更改aMemberotherMember:

template< class T, class = void_t<> >
struct has_otherMember : std::false_type { };

template< class T >
struct has_otherMember<T, void_t<decltype( T::otherMember )>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)

我想避免这种复制粘贴,并将成员名称作为参数传递给更通用的检测模板版本:

template< class T, class member, class = void_t<> >
struct has_arbitrary_member : std::false_type { };

template< class T, class member >
struct has_arbitrary_member<T, void_t<decltype( T::member )>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)

所以我可以has_arbitrary_member通过将类型和成员名称作为模板参数传递来使用它:

 std::cout << has_arbitrary_member<MyType, aMember>();
 std::cout << has_arbitrary_member<MyType, otherMember>();
Run Code Online (Sandbox Code Playgroud)

但是,根据我上面草拟的定义​​,这将无法编译.有没有其他方法来实现这样的功能?

Bri*_*ian 8

一般情况下,您尝试执行的操作是不可能的,因为除非使用宏修改令牌流,否则无法禁止名称查找aMember.因此,除非您当前 SFINAE 内,否则您永远无法使用不在范围内的名称,这将抑制错误.

这意味着您确实必须为每个名称编写单独的模板.

这是使用宏并不是一个坏主意的情况之一,尽管这取决于您是否确实需要检查特定名称的成员,或者是否有更好的方法来实现您的目标.