【发布时间】:2021-06-05 11:02:29
【问题描述】:
对不起标题,我不确定我的问题的类别。 我正在尝试用 SFINAE 做一个 is_incrementable。这很好用,但是当我尝试更深入地理解它时,当我删除 void_t 时,代码 sn-p 无法按预期工作。
原代码:
#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,它也是原始模板类和特化。在这种情况下,编译器选择了专门的版本,所以值等于 1。
对于字符串版本,特化失败,SFINAE 启动,所以我们只有基本模板。 (值等于0)
ii) 当我更改代码并删除 void_t
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(我认为),所以我们使用基本模板。对于字符串,特化无论如何都会失败。
我的问题: iii) 有趣的部分。 如果现在我将第一行更改为使用 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) 中发生了什么。
【问题讨论】: