非终止地递归使用decltype
Non-terminating recursive use of decltype
由于无限编译时递归,以下代码的编译存在问题。Clang 3.6.0给出了一个关于递归模板实例化深度的错误,并且没有终止;而GCC 4.9.2保持沉默,也不会终止。
这是一个比我最初面对的更简单的例子,当然bar
的第二次重载可以将int
作为返回类型;在这种情况下,对main
中的bar
的调用选择第一个过载;正如我最初希望的那样。为什么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;
}
这失败是因为decltype
表达式需要为这些参数计算出bar
的返回类型,所以它需要实例化所有bar
模板,这涉及到查看需要为这些参数计算出bar
的返回类型的decltype
表达式,所以它需要实例化所有bar
模板…我相信你可以想象这最终会导致编译器崩溃。
T
是Foo
时,我们可以禁用重载:
namespace detail {
template <typename T>
struct is_foo : std::false_type{};
template <typename T, typename A>
struct is_foo<Foo<T,A>> : std::true_type{};
}
template <typename T>
using is_foo = detail::is_foo<typename std::decay<T>::type>;
template <typename T, typename A>
int bar(const Foo<T,A> &x) { return 0; }
template <typename T,
typename = typename std::enable_if<!is_foo<T>::value>::type>
auto bar(const T &x)
-> decltype(bar(Foo<T>{})){
Foo<T> b{};
return bar(b);
}
相关文章:
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- decltype用于递归变元函数模板的返回类型
- 为什么decltype返回类型在递归模板中失败,而返回类型演绎却工作得很好?
- 非终止地递归使用decltype
- C++变量模板,递归decltype
- decltype,重载运算符的递归类型推导