如何解决没有 void_t 的 SFINAE可能是模板专业化问题
抱歉标题,我不确定我的问题的类别。 我正在尝试使用 SFINAE 进行 is_incrementable。这很好用,但是当我尝试更深入地理解它时,当我删除 void_t 时,代码片段无法按预期工作。
原代码:
#include <iostream>
template< typename,typename = void >
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,std::void_t<decltype( ++std::declval<T&>() )>
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 1
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
i) is_incrementable<int>::value
的计算结果为 is_incrementable<int,void>::value
,它也是原始模板类和特化。在这种情况下,编译器选择专用版本,因此将 eguals 赋值为 1。
对于字符串版本,特化失败,SFINAE 启动,所以我们只有基本模板。 (值等于0)
template< typename,typename = void >
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,decltype( ++std::declval<T&>() ) // void_t is removed
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 0
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
0 和 0 被打印出来。
is_incrementable<int>::value
表示 is_incrementable<int,void>::value
,特化是
is_incrementable<int,int>::value
(我认为),所以我们使用基本模板。对于字符串,特化无论如何都会失败。
我的问题: 三) 有趣的部分。 如果现在我将第一行更改为使用 int 作为默认类型
#include <iostream>
template< typename,typename = int > // !!! int is used Now
struct is_incrementable : std::false_type { };
template< typename T >
struct is_incrementable<T,decltype( ++std::declval<T&>() ) // void_t is removed
> : std::true_type { };
int main()
{
std::cout << is_incrementable<int>::value << std::endl; // prints 0
std::cout << is_incrementable<std::string>::value << std::endl; // prints 0
return 0;
}
然后再次打印 0 和 0。
为什么?
is_incrementable<int>::value
的意思是(我认为)is_incrementable<int,int>::value
和
decltype( ++std::declval<T&>() )
也应该是 int。
所以我认为编译器应该使用专门的版本。 (应该打印 1)
如果我删除
decltype( ++std::declval<T&>() )
并写入 int
然后打印 1 和 1(这是预期的打印输出)。
有人能解释一下 iii) 中发生了什么吗。
解决方法
当 T
为 int
时,decltype( ++std::declval<T&>() )
为 int &
,而不是 int
。所以为了得到你期望的输出,你要么改变这个:
template< typename,typename = int >
struct is_incrementable : std::false_type { };
为此:
template< typename,typename = int & >
struct is_incrementable : std::false_type { };
或者改变这个:
template< typename T >
struct is_incrementable<T,decltype( ++std::declval<T&>() )
> : std::true_type { };
为此:
template< typename T >
struct is_incrementable<T,std::remove_reference_t<
decltype( ++std::declval<T&>() )
>
> : std::true_type { };
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。