基于constexpr的计算图灵完成?
我们知道C ++模板元编程是图灵完备的 ,但是预处理元编程不是 。
C ++ 11为我们提供了一种新的元编程forms:计算constexpr函数。 这种计算forms是否是图灵完成的? 我在想,因为recursion和条件运算符(?:)在constexpr函数中是允许的,但是我希望有更多专业知识的人来确认。
tl; dr:C ++ 11中的constexpr
由于语言规范中的错误而不是图灵完成的,但是该错误已经在标准的后续草稿中得到解决,并且clang已经实现了该修复。
如ISO C ++ 11国际标准所规定的, constexpr
不是图灵完备的。 素描certificate:
- 每一个
constexpr
函数f
的结果(或非终止)在一个特定的参数序列,a...
,只能由一个值的决定a...
- 可以在常量expression式中构造的每个参数值必须是一个文字types,由
[basic.types]p10
可以是:- 一个标量types,
- 一个参考,
- 一个字面types的数组,或者
- 一个类的types
- 上述每种情况都有一组有限的值。
- 对于一个标量的非指针types来说,这是非常平常的。
- 对于在常量expression式中使用的指针或引用,必须通过地址或引用常量expression式进行初始化,所以必须引用具有静态存储持续时间的对象,其中在任何程序中只有有限的数量。
- 对于一个数组来说,bound必须是一个常量,并且每个成员都必须用一个常量expression式进行初始化,结果如下。
- 对于一个类types来说,成员数量是有限的,每个成员必须是字面types,并用一个常量expression式进行初始化,结果如下。
- 因此,
f
可以接收的a...
组可能的input是有限的,所以任何有限状态的constexpr
系统都是一个有限状态机,因此不是图灵完备的。
但是,自从C ++ 11标准发布以来,情况就发生了变化。
Johannes Schaub对std :: max()和std :: min()不是constexpr的回答中描述的问题作为核心问题1454被报告给C ++标准化委员会。在2012年2月的WG21会议上,我们认定这是一个缺陷标准和选定的解决scheme包括能够使用指定临时对象的指针或引用成员来创build类types的值。 这允许一个无限量的信息被一个constexpr
函数累加和处理,并且足以进行constexpr
评估。图灵完成(假设这个实现支持recursion到一个无限深度)。
为了演示实现1454核心问题的解决scheme的编译器的constexpr
的图灵完备性,我为叮当testing套件写了一个图灵机模拟器:
http://llvm.org/svn/llvm-project/cfe/trunk/test/SemaCXX/constexpr-turing.cpp
g ++和clang的中继版本实现了这个核心问题的解决scheme,但是g ++的实现目前无法处理这个代码。
看看这些。 我编译了这些例子,他们在GCC 4.6中工作: 编译时计算 , 编译时 parsingstring – 第一部分 , 编译时parsingstring – 第二部分
如果考虑到实际计算机的限制 – 比如有限内存和MAX_INT的有限值,那么当然,constexpr(以及整个C ++)不是图灵完备的。
但是,如果我们将删除这个限制 – 例如,如果我们将int看作一个完全任意的正整数 – 那么是的,C ++的constexpr部分将是Turing完成的。 很容易expression任何部分recursion函数。
0,S(n)= n + 1,select符I_n ^ m(x_1,…,x_n)= x_m,明显的叠加可以用constexpr表示。
原始recursion可以直接完成:
constexpr int h(int x1, ..., int xn, int y) { return (xn == 0) ? f(x1, ..., xn) : g(x1, ..., xn, y-1, h(x1, ..., xn, y-1)); }
对于部分recursion,我们需要一个简单的技巧:
constexpr int h(int x1, ... int xn, int y = 0) { return (f(x1, ... xn, y) == 0) ? y : h(x1, ..., xn, y+1); }
所以我们得到任何部分recursion函数作为constexpr。