非终止递归使用decltype

时间:2015-09-02 10:27:56

标签: c++ templates c++11 recursion

由于无限的编译时递归,以下代码的编译存在问题。 Clang 3.6.0给出了关于递归模板实例化深度的错误,并且没有终止;虽然GCC 4.9.2保持沉默,但也没有终止。

这是一个比我最初面对的更简单的例子,当然bar的第二次重载可以作为返回类型给出int;在这种情况下,选择第一个重载来调用bar中的main;正如我原本希望的那样。为什么decltype的应用程序无法解析为第一个重载,专门用于Foo

Foo的第二个(默认)模板参数似乎隐藏了有关递归问题的更详细消息。这在原始语境中很有用。

template <typename T, typename A = T>
struct Foo {};

template <typename T, typename A>
int bar(const Foo<T,A> &x) { return 0; }

template <typename T>
auto bar(const T &x)
 -> decltype(bar(Foo<T>{})){    
    return   bar(Foo<T>{});    
}

int main(int argc, char *argv[])
{
  Foo<char> f;    
  bar(f);

  return 0;
}

1 个答案:

答案 0 :(得分:4)

这会失败,因为decltype表达式需要为这些参数计算出bar的返回类型,因此需要实例化所有bar模板,这涉及查看{ {1}}表达式需要为这些参数计算出decltype的返回类型,因此它需要实例化所有bar模板...我相信你可以想象这最终如何导致让编译器崩溃。

在C ++ 14中,我们可以省略尾随返回类型以避免所有这些工作。在C ++ 11中,我们可以在barT

时禁用该重载
Foo