我观看了Walter Brown在Cppcon14上有关现代模板编程的演讲(第一部分,第二部分),他介绍了他的void_tSFINAE技术。
示例:
给定一个简单的变量模板,该模板评估void所有模板参数是否格式正确:
template< class ... > using void_t = void;
以及以下特征来检查是否存在称为member的成员变量:
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 , void_t< decltype( T::member ) > > : std::true_type
{ };
我试图理解为什么和如何工作。因此,一个小例子:
class A {
public:
int member;
};
class B {
};
static_assert( has_member< A >::value , "A" );
static_assert( has_member< B >::value , "B" );
1。 has_member< A >
has_member< A , void_t< decltype( A::member ) > >A::member存在decltype( A::member )格式正确void_t<>有效且评估为void
has_member< A , void >因此,它选择了专门的模板has_member< T , void >并评估为true_type
2。 has_member< B >
has_member< B , void_t< decltype( B::member ) > >B::member不存在decltype( B::member )病态严重,无声地失败(sfinae)has_member< B , expression-sfinae >所以这个模板被丢弃了
- 编译器发现
has_member< B , class = void >void为默认参数 has_member< B >评估为false_type
问题:
1.我对此的理解正确吗?
2. Walter Brown指出,默认参数必须与工作时使用的参数完全相同void_t。这是为什么?(我不知道为什么需要匹配这些类型,难道不仅仅是工作需要任何默认类型吗?)
has_member< T , class = void >默认设置的必要void。假设此特征在任何时候都只能与1个模板参数一起使用,那么默认参数可以是任何类型吗?
template <class, class = void>为template <class, class = void_t<>>。因此,现在我们可以随意使用void_t别名模板实现来做我们想做的所有事情了:)
has_member<A,int>::value。然后,评估为的局部专业has_member<A,void>无法匹配。因此,它必须是has_member<A,void>::valuetype的默认参数,或者与语法糖一起使用void。