【发布时间】:2015-10-13 17:44:44
【问题描述】:
使用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 { };
现在,如果我想检测是否存在其他成员,我必须复制粘贴检测器模板并将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 { };
我想避免这种复制粘贴并将成员名称作为参数传递给更通用的检测模板版本:
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 { };
这样我就可以通过将类型和成员名称作为模板参数传递来使用这个has_arbitrary_member:
std::cout << has_arbitrary_member<MyType, aMember>();
std::cout << has_arbitrary_member<MyType, otherMember>();
但是,根据我上面起草的定义,这将无法编译。有没有其他方法可以实现这样的功能?
【问题讨论】:
-
你能做的最好的事情就是
std::experimental::is_detected。 -
“喜欢”是什么意思? above 的代码块like 这两行。你的硬性要求是什么,它们上面的代码块是如何不符合你的要求的?我可以在上面写一个更好的代码版本(比如
is_detected),但如果这是你想要的,我就没有办法了。 -
@Yakk 我在问题的末尾添加了一句话,以更清楚地说明我的意图。当然 void_t 不是必需的,尽管我看到
is_detected是使用void_t本身实现的。这有帮助吗? -
@Rostislav:恕我直言,这仍然有点不清楚。您可以使用 T::myMember 获得 SFINAE,因此无论如何模板选择都应该起作用。您能否举例说明您希望代码的外观(不需要为每个数据成员检测器)?
-
@AndyG 这样更好吗?