当前位置: 首页 > 知识库问答 >
问题:

没有void_t的SFINAE(可能是模板专门化问题)

白和泽
2023-03-14
#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;
}

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 ::value 表示is_incrementable ::value ,专门化是is_incrementable ::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;
}

有人能给我解释一下在iii)发生了什么吗?

共有1个答案

魏安宁
2023-03-14

tint时,decltype(++std::declval ()) 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 { };
 类似资料:
  • 我知道,我可能可以用SFINAE和函数重载单独做到这一点。但是,对于像这样的情况,使用SFINAE是一种矫枉过正的做法。 所以我想知道是否有干净的方法来混合模板专业化和sfinae。

  • 但是指定它是,因此它不再是模板类。它是否可以像虚函数一样专门化或重写?

  • 还尝试在专门化的中进行模板方法专门化: 这一次它编译,但调用原始方法,即 解决方案

  • 我有一个通用算法,需要访问其模板类型的特征。有一个特征类可以专门用于提供这些特征。 在我的类中使用此算法时,我想将其与类中定义的私有类型一起使用。 然而,专门化只能发生在或全局范围内,而我的类是不可访问的。 是否有可能以某种方式专门化具有私有类型的模板,至少在可访问此类型的范围内? 也许可以将这个专门化声明为一个类?

  • 对于将SFINAE与可变模板类一起使用,我似乎找不到一个好的解决方案。 假设我有一个不喜欢引用的可变参数模板对象: 以及一个类,可以方便地检查参数包是否包含引用: 我如何使用它来专门化NoRef的情况下,引用存在于arg包?

  • 在SO上回答另一个问题时,我遇到了一个有点可疑的gcc编译器错误。令人不快的片段是 谁的最后一行给出了著名的警告 好友声明'