我观看了Walter Brown在Cppcon14上有关现代模板编程的演讲(第一部分,第二部分),他介绍了他的void_t
SFINAE技术。
示例:
给定一个简单的变量模板,该模板评估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>::value
type的默认参数,或者与语法糖一起使用void
。