没有 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)

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(我认为),所以我们使用基本模板。对于字符串,特化无论如何都会失败。

我的问题: 三) 有趣的部分。 如果现在我将第一行更改为使用 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>::valuedecltype( ++std::declval<T&>() ) 也应该是 int。 所以我认为编译器应该使用专门的版本。 (应该打印 1)

如果我删除 decltype( ++std::declval<T&>() ) 并写入 int 然后打印 1 和 1(这是预期的打印输出)。

有人能解释一下 iii) 中发生了什么吗。

解决方法

Tint 时,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 { };

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...