我打算让我的问题成为以下问题的后续:我们如何将 void_t 用于 SFINAE?。我明白了 void_t 是如何使用的。我不明白为什么有必要。
让我们以该问题为例并删除 void_t
template< class , class = void >
struct has_member : std::false_type
{ };
// specialized as has_member< T , void > or discarded (SFINAE)
template< class T >
struct has_member< T , decltype( T::member ) > : std::true_type
{ };
如果我传入一个不带“member”的对象,它仍将默认为默认模板,而带有“member”的对象将实例化专业化。
为什么这种想法有缺陷?我认为这与主模板的第二个模板参数具有默认值(“class = void”)有关。但我不明白为什么这很重要。为什么专业化必须使用“void_t”来匹配默认参数?难道默认的全部意义不是可以被覆盖吗?我在哪里可以阅读有关 cppreference.com 主题的更多信息?
您的主模板除其他外指定第二个模板参数默认为
void
;因此,对于任何类型 A
,has_member<A>
均表示 has_member<A, void>
。
现在,假设
A
有一个名为 member
类型为 int
的公共成员:
class A {
public:
int member;
};
这意味着
decltype( T::member )
是 int
,因此您的模板特化提供了 has_member<A, int>
的特化。这是完全正确的!但这不是您想要的 — 您想要的是 has_member<A>
的专业化,即
has_member<A, void>
。这有道理吗?