C++ 模板图灵完备?
I'm told that the template system in C++ is Turing-complete at compile time. This is mentioned in this post and also on wikipedia.
Can you provide a nontrivial example of a computation that exploits this property?
Is this fact useful in practice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我用 C++11 做了一个图灵机。 C++11 添加的功能对于图灵机来说确实并不重要。 它只是使用可变参数模板提供任意长度的规则列表,而不是使用不正当的宏元编程:)。 条件的名称用于在标准输出上输出图表。 我删除了该代码以保持示例简短。
I've done a turing machine in C++11. Features that C++11 adds are not significant for the turing machine indeed. It just provides for arbitrary length rule lists using variadic templates, instead of using perverse macro metaprogramming :). The names for the conditions are used to output a diagram on stdout. i've removed that code to keep the sample short.
示例
这有点有趣,但不太实用。
回答问题的第二部分:
这个事实在实践中有用吗?
简短的回答:有点。
长答案:是的,但前提是您是模板守护程序。
使用对其他人使用确实有用的模板元编程(即库)进行良好的编程确实非常困难(尽管可行)。 为了帮助提升甚至有 MPL 又名(Meta编程库)。 但是尝试调试模板代码中的编译器错误,您将经历一段漫长的艰难历程。
但它被用于有用的事情的一个很好的实际例子是:
Scott Meyers 一直在使用模板工具对 C++ 语言(我宽松地使用这个术语)进行扩展。 您可以在此处阅读有关他的工作“强制执行代码功能”
Example
That was a little fun but not very practical.
To answer the second part of the question:
Is this fact useful in practice?
Short Answer: Sort of.
Long Answer: Yes, but only if you are a template daemon.
To turn out good programming using template meta-programming that is really useful for others to use (ie a library) is really really tough (though do-able). To Help boost even has MPL aka (Meta Programming Library). But try debugging a compiler error in your template code and you will be in for a long hard ride.
But a good practical example of it being used for something useful:
Scott Meyers has been working extensions to the C++ language (I use the term loosely) using the templating facilities. You can read about his work here 'Enforcing Code Features'
我的 C++ 有点生疏,所以可能不完美,但已经很接近了。
重点是证明编译器正在完全评估递归定义,直到得出答案。
My C++ is a bit rusty, so the may not be perfect, but it's close.
The point is to demonstrate that the compiler is completely evaluating the recursive definition until it reaches an answer.
举一个重要的例子: https://github.com/phresnel/metatrace ,一个 C++编译时光线追踪器。
请注意,C++0x 将以 constexpr 的形式添加非模板、编译时、图灵完备的工具:
您可以在任何需要的地方使用 constexpr-表达式编译时常量,但您也可以使用非常量参数调用 constexpr 函数。
一件很酷的事情是,这最终将启用编译时浮点运算,尽管标准明确指出编译时浮点运算不必与运行时浮点运算相匹配:
To give a non-trivial example: https://github.com/phresnel/metatrace , a C++ compile time ray tracer.
Note that C++0x will add a non-template, compile-time, turing-complete facility in form of
constexpr
:You can use
constexpr
-expression everywhere where you need compile time constants, but you can also callconstexpr
-functions with non-const parameters.One cool thing is that this will finally enable compile time floating point math, though the standard explicitly states that compile time floating point arithmetics do not have to match runtime floating point arithmetics:
阶乘示例实际上并不表明模板是图灵完整的,尽管它表明它们支持原始递归。 证明模板是图灵完备的最简单方法是通过 Church-Turing 论文,即通过实现图灵机(混乱且有点毫无意义)或非类型化 lambda 演算的三个规则(app、abs var)。 后者更简单也更有趣。
当您了解 C++ 模板允许在编译时进行纯函数式编程时,所讨论的是一个非常有用的功能,这是一种富有表现力、强大而优雅的形式主义,但如果您经验很少,那么编写起来也会非常复杂。 另请注意,有多少人发现仅仅获得高度模板化的代码通常需要付出很大的努力:这正是(纯)函数式语言的情况,这使得编译变得更加困难,但令人惊讶的是生成不需要调试的代码。
The factorial example actually does not show that templates are Turing complete, as much as it shows that they support Primitive Recursion. The easiest way to show that templates are turing complete is by the Church-Turing thesis, that is by implementing either a Turing machine (messy and a bit pointless) or the three rules (app, abs var) of the untyped lambda calculus. The latter is much simpler and far more interesting.
What is being discussed is an extremely useful feature when you understand that C++ templates allow pure functional programming at compile time, a formalism that is expressive, powerful and elegant but also very complicated to write if you have little experience. Also notice how many people find that just getting heavily templatized code can often require a big effort: this is exactly the case with (pure) functional languages, which make compiling harder but surprisingly yield code that does not require debugging.
好吧,这是一个编译时图灵机实现,运行 4 状态 2 符号繁忙海狸
Ideone 证明运行:https://ideone。 com/MvBU3Z
说明:http://victorkomarov。 blogspot.ru/2016/03/compile-time-turing-machine.html
Github 上有更多示例:https ://github.com/fnz/CTTM
Well, here's a compile time Turing Machine implementation running a 4-state 2-symbol busy beaver
Ideone proof run: https://ideone.com/MvBU3Z
Explanation: http://victorkomarov.blogspot.ru/2016/03/compile-time-turing-machine.html
Github with more examples: https://github.com/fnz/CTTM
我认为它被称为模板元编程。
I think it's called template meta-programming.
有趣的是,它是一种纯函数式语言,尽管几乎不可能调试。 如果您查看 James 帖子,您就会明白我所说的功能性是什么意思。 一般来说,这不是 C++ 最有用的功能。 它的设计目的不是为了这样做。 这是被发现的东西。
It's also fun to point out that it is a purely functional language albeit nearly impossible to debug. If you look at James post you will see what I mean by it being functional. In general it's not the most useful feature of C++. It wasn't designed to do this. It's something that was discovered.
如果您想在编译时计算常量,它可能很有用,至少在理论上是这样。 查看模板元编程。
It may be useful if you want to compute constants at compile time, at least in theory. Check out template metaprogramming.
一个相当有用的例子是比率类。 目前存在一些变体。 通过部分重载捕获 D==0 的情况相当简单。 真正的计算是计算N和D的GCD以及编译时间。 当您在编译时计算中使用这些比率时,这一点至关重要。
示例:当您计算厘米(5)*公里(5)时,在编译时您将乘以比率<1,100> 和比率<1000,1>。 为了防止溢出,您需要一个比率<10,1> 而不是比率<1000,100>。
An example which is reasonably useful is a ratio class. There are a few variants floating around. Catching the D==0 case is fairly simple with partial overloads. The real computing is in calculating the GCD of N and D and compile time. This is essential when you're using these ratios in compile-time calculations.
Example: When you're calculating centimeters(5)*kilometers(5), at compile time you'll be multiplying ratio<1,100> and ratio<1000,1>. To prevent overflow, you want a ratio<10,1> instead of a ratio<1000,100>.
图灵机是图灵完备的,但这并不意味着您应该使用一台用于生产代码。
根据我的经验,尝试使用模板做任何不平凡的事情都是混乱、丑陋和毫无意义的。 您无法“调试”您的“代码”,编译时错误消息将是神秘的,并且通常出现在最不可能的地方,并且您可以通过不同的方式实现相同的性能优势。 (提示:4!= 24)。 更糟糕的是,您的代码对于普通 C++ 程序员来说是难以理解的,并且由于当前编译器内广泛的支持级别而可能无法移植。
模板非常适合通用代码生成(容器类、类包装器、混合),但不行 - 在我看来,模板的图灵完备性在实践中没有用。
A Turing machine is Turing-complete, but that doesn't mean you should want to use one for production code.
Trying to do anything non-trivial with templates is in my experience messy, ugly and pointless. You have no way to "debug" your "code", compile-time error messages will be cryptic and usually in the most unlikely places, and you can achieve the same performance benefits in different ways. (Hint: 4! = 24). Worse, your code is incomprehensible to the average C++ programmer, and will be likely be non-portable due to wide ranging levels of support within current compilers.
Templates are great for generic code generation (container classes, class wrappers, mix-ins), but no - in my opinion the Turing Completeness of templates is NOT USEFUL in practice.
另一个如何不编程的例子:
发布于 C++模板图灵完备
Just another example of how not to program :
Post at C++ templates are turing complete