【发布时间】:2020-02-20 21:45:39
【问题描述】:
以下代码在由我测试过的每个 C++ 编译器编译时崩溃或挂起,直到内存耗尽:
#include <tuple>
template<class... Ts>
auto f(Ts... ts){
return f(std::make_tuple(ts...));
}
auto a = f();
在各种版本的 GCC、Clang、MSVC、icc、ELLCC 上测试:https://godbolt.org/z/cwqiZK
我的问题是,为什么这些编译器实现的模板深度限制或类似的安全措施没有发现这一点?我发现了一些导致编译器挂起的代码示例like this old example,但似乎我能找到的所有问题都已得到修复,因为它已成为限制模板实例化深度的标准。
我应该注意,这不是 make_tuple 独有的,适用于 tie、forward_as_tuple... 等。
作为警告,如果您尝试在本地编译它,请务必使用ulimit 之类的内容,以确保编译器不会耗尽您的内存。在玩这个时,我不得不硬重启几次。
【问题讨论】:
-
它们确实有深度限制,但在这种情况下,所需的内存可能会随着深度的二次方增长,因为您将拥有 std::tuple<:tuple>> (N 层) 在第 N 级。
-
" 如果您尝试在本地编译,请务必使用类似 ulimit" 或手动使用 (gcc) 标志
-ftemplate-depth=XDemo。 -
这有点像为什么编译器不解决停机问题。
-
@Barry,是吗?在这种情况下,提供了很多信息来知道停止是不可能的。
-
@JeffreyCash:“是吗?”是的。在许多情况下,您可以确定是否可以在多种语言中停止,但这并不意味着编译器应该尝试这样做。仅仅因为你可以看到无限递归并不意味着我们应该让编译器尝试做同样的事情。