Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ decltype(自动)在某些情况下与SFINAE一起工作?_C++_C++17_Sfinae - Fatal编程技术网

C++ decltype(自动)在某些情况下与SFINAE一起工作?

C++ decltype(自动)在某些情况下与SFINAE一起工作?,c++,c++17,sfinae,C++,C++17,Sfinae,我假设decltype(auto)在用于尝试和取消返回类型时是一个不兼容的构造。所以,当你本来会得到一个替换错误时,你会得到一个硬错误 但是为什么下面的程序会起作用呢 #包括 #包括 使用std::cout; 使用std::endl; 模板 类标识{ 公众: 使用类型=T; }; 模板 decltype(自动)构造(T&&){ 返回T{}; } 模板 福班{ 公众: 静态void foo(){ 库特 我假设decltype(auto)在用于尝试和取消返回类型时是一个不兼容的构造 它通常是不兼容的

我假设
decltype(auto)
在用于尝试和取消返回类型时是一个不兼容的构造。所以,当你本来会得到一个替换错误时,你会得到一个硬错误

但是为什么下面的程序会起作用呢

#包括
#包括
使用std::cout;
使用std::endl;
模板
类标识{
公众:
使用类型=T;
};
模板
decltype(自动)构造(T&&){
返回T{};
}
模板
福班{
公众:
静态void foo(){
库特
我假设
decltype(auto)
在用于尝试和取消返回类型时是一个不兼容的构造

它通常是不兼容的,因为它强制实例化函数体。如果函数体中发生替换失败,那么这将是一个硬编译错误-SFINAE在这里不适用

然而,在本例中,在主体中获得替换失败的唯一方法是如果
T
不是默认可构造的。但是您调用
construct(T{})
,这已经要求
T
是默认可构造的-因此失败将首先发生,或者永远不会发生

相反,发生的替换失败是在替换为
typename decltype(construct(T{}))::type
的直接上下文中发生的。当我们在将模板参数实例化为
Foo
的直接上下文中时,尝试将
::type
int
中移除时,因此SFINAE仍然适用

演示
decltype(auto)
在何处中断SFINAE的一个示例是,我们是否将其实现为:

template <typename T>
decltype(auto) construct() {
  return T{};
}

template <typename T, typename = std::void_t<>>
class Foo {
public:
  static void foo() {
    cout << "Nonspecialized foo called" << endl;
  }
};
template <typename T>
class Foo<T,
          std::void_t<typename decltype(construct<T>())::type>> {
public:
  static void foo() {
    cout << "Specialized foo called" << endl;
  }
};
模板
decltype(自动)构造(){
返回T{};
}
模板
福班{
公众:
静态void foo(){

可以啊,这很有道理!我的理解显然是不完整的。谢谢!为了完整起见,你能指出标准中的相关部分吗?不知何故,我仍然没有在这里得到错误-?@奇怪,因为现在
t{}
首先在直接上下文中。
template <typename T>
decltype(auto) construct() {
  return T{};
}

template <typename T, typename = std::void_t<>>
class Foo {
public:
  static void foo() {
    cout << "Nonspecialized foo called" << endl;
  }
};
template <typename T>
class Foo<T,
          std::void_t<typename decltype(construct<T>())::type>> {
public:
  static void foo() {
    cout << "Specialized foo called" << endl;
  }
};
struct X {
    X(int);
};

Foo<X>::foo(); // hard error, failure is in the body of construct()