简体   繁体   English

C++ 使编译循环永远存在的代码示例

[英]C++ code example that makes the compile loop forever

Given that the C++ template system is not context-free and it's also Turing - Complete , can anyone provide me a non-trivial example of a program that makes the g++ compiler loop forever?鉴于 C++ 模板系统不是上下文无关的,而且它也是Turing - Complete ,任何人都可以为我提供一个使 g++ 编译器永远循环的程序的重要示例吗?

For more context, I imagine that if the C++ template system is Turing-complete, it can recognize all recursively enumerable languages and decide over all recursive ones.对于更多上下文,我想如果 C++ 模板系统是图灵完备的,它可以识别所有递归可枚举语言并决定所有递归语言。 So, it made me think about the acceptance problem, and its more famous brother, the halting problem.所以,这让我想到了验收问题,以及它更有名的兄弟,即停机问题。 I also imagine that g++ must decide if the input belongs in the C++ language (as it belongs in the decidability problem) in the syntactic analysis.我还想象 g++ 必须在句法分析中决定输入是否属于 C++ 语言(因为它属于可判定性问题)。 But it also must resolve all templates, and since templates are recursively enumerable, there must be a C++ program that makes the g++ syntactic analysis run forever, since it can't decide if it belongs in the C++ grammar or not.但它也必须解析所有模板,并且由于模板是递归可枚举的,因此必须有一个 C++ 程序使 g++ 语法分析永远运行,因为它无法确定它是否属于 C++ 语法。

I would also like to know how g++ deals with such things?我也想知道g++是怎么处理这种事情的?

While this is true in theory for the unlimited language, compilers in practice have implementation limits for recursive behavior (eg how deep template instantiations can be nested or how many instructions can be evaluated in a constant expression), so that it is probably not straight-forward to find such a case, even if we somehow ignore obvious problems of bounded memory. The standard specifically permits such limits, so if you want to be pedantic I am not even sure that any given implementation has to satisfy these theoretical concepts.虽然这在理论上对于无限语言是正确的,但实践中的编译器对递归行为有实现限制(例如,可以嵌套多深的模板实例化或可以在常量表达式中评估多少条指令),因此它可能不是直接的 -即使我们以某种方式忽略了有界 memory 的明显问题,也可以找到这样的情况。标准明确允许这样的限制,所以如果你想学究气,我什至不确定任何给定的实现都必须满足这些理论概念。

And also infinitely recursive template instantiation specifically is forbidden by the language.而且语言还特别禁止无限递归模板实例化。 A program with such a construct has undefined behavior and the compiler can just refuse to compile if it is detected (although of course it cannot be detected in general).具有这种构造的程序具有未定义的行为,编译器可以在检测到它时拒绝编译(当然,通常无法检测到)。

This shows the limits for clang: Apple clang version 13.1.6 (clang-1316.0.21.2.5)这显示了 clang 的限制: Apple clang version 13.1.6 (clang-1316.0.21.2.5)

#include <iostream>

template<int V>
struct Count
{
    static constexpr int value = Count<V-1>::value + 1;
};

template<>
struct Count<1>
{
    static constexpr int value = 1;
};

int main()
{
#ifdef WORK
    int v = Count<1026>::value;  // This works.
#else
    int v = Count<1027>::value;  // This will fail to compile.
#endif
    std::cout << "V: " << v << "\n";
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM