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)
现在,如果我想检测是否存在其他成员,我将不得不复制粘贴检测器模板,只需更改aMember
为otherMember
:
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)
但是,根据我上面草拟的定义,这将无法编译.有没有其他方法来实现这样的功能?
一般情况下,您尝试执行的操作是不可能的,因为除非使用宏修改令牌流,否则无法禁止名称查找aMember
.因此,除非您当前在 SFINAE 内,否则您永远无法使用不在范围内的名称,这将抑制错误.
这意味着您确实必须为每个名称编写单独的模板.
这是使用宏并不是一个坏主意的情况之一,尽管这取决于您是否确实需要检查特定名称的成员,或者是否有更好的方法来实现您的目标.