是基于constexpr的计算图灵完备
Is constexpr-based computation Turing complete?
我们知道C++模板元编程是图灵完备的,但预处理器元编程不是。
C++11为我们提供了一种新的元编程形式:constexpr函数的计算。这种形式的计算图灵是完整的吗?我在想,由于递归和条件运算符(?:)在constexpr函数中是允许的,这是可以的,但我希望有更专业的人来证实。
tl;dr:constexpr
在C++11中并不完全是图灵的,这是由于语言规范中的一个错误,但这个错误已经在后来的标准草案中得到了解决,clang已经实现了修复。
ISO C++11国际标准中规定的constexpr
不是图灵完备的。草图证明:
- 每个
constexpr
函数f
在特定参数序列a...
上的结果(或非终止)仅由a...
的值确定 - 可以在常量表达式中构造的每个参数值都必须是文字类型,根据
[basic.types]p10
,文字类型为:- 标量类型
- 参考
- 文字类型的数组,或
- 类类型
- 上述每种情况都有一组有限的值。
- 对于标量、非指针类型,下面将简单介绍
- 对于要在常量表达式中使用的指针或引用,它必须由地址或引用常量表达式初始化,因此必须引用具有静态存储持续时间的对象,在任何程序中,该对象的数量都是有限的
- 对于数组,绑定必须是一个常量,并且每个成员都必须由一个常量表达式初始化,然后得出结果
- 对于类类型,有有限数量的成员,每个成员都必须是文字类型,并由常量表达式初始化,结果如下
- 因此,
f
可以接收的可能输入a...
的集合是有限的,因此任何有限描述的constexpr
系统都是有限状态机,因此不是图灵完备的
然而,自从C++11标准发布以来,情况发生了变化。
Johannes Schaub对std::max()和std::min()not constexpr的回答中描述的问题作为核心问题1454报告给C++标准化委员会。在2012年2月的WG21会议上,我们决定这是标准中的一个缺陷,所选择的决议包括使用指定临时成员的指针或引用成员创建类类型值的能力。这允许constexpr
函数累积和处理无界数量的信息,并且足以使constexpr
评估图灵完成(假设实现支持递归到无界深度)。
为了证明constexpr
对于实现核心问题1454的拟议解决方案的编译器的图灵完备性,我为clang的测试套件编写了一个图灵机模拟器:
https://github.com/llvm/llvm-project/blob/main/clang/test/SemaCXX/constexpr-turing.cpp
Clang 3.1和g++9以后的版本都在其C++11模式中实现了固定规则,并且可以处理该示例。
看看这些。我整理了这些例子,它们在GCC 4.6中起作用:编译时计算,编译时解析字符串-第一部分,编译时分析字符串-第二部分
如果我们考虑到真实计算机的限制,例如有限内存和MAX_INT的有限值,那么constexpr(以及整个C++)当然不是图灵完备的。
但如果我们去掉这个限制——例如,如果我们将int视为一个完全任意的正整数——那么是的,C++的constexpr部分将是图灵完备的。表示任何部分递归函数都很容易。
0,S(n)=n+1,选择器I_n^m(x_1,…,x_n)=x_m和叠加显然可以用constexpr表示。
基元递归可以直接完成:
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));
}
对于部分递归,我们需要一个简单的技巧:
constexpr int h(int x1, ... int xn, int y = 0) {
return (f(x1, ... xn, y) == 0) ? y : h(x1, ..., xn, y+1);
}
因此,我们将任何部分递归函数作为constexpr。
- OpenCV - Python 断言错误:SAD 算法 - 立体相机视差图计算
- 计算无向未加权图的每个连接部分中的节点数
- 有向图 - 如何计算图中彼此顶点可到达的顶点数?
- 英特尔 TBB 计算图:如何指定节点的输入队列容量
- C++计算有向图中的最短路径
- 可以在提升图库中即时计算边
- 如何计算位图大小
- 避免计算图中的虚函数调用
- 当我有点的坐标时,如何在图中计算内部角度
- 计算图中路径的递归函数的复杂性
- 使用 BITMAP 计算位图的内存使用情况
- 计算二分图中的路径数(长度 n)
- 是基于constexpr的计算图灵完备
- 计算给定无向图中线性生成树的个数
- 计算图中节点的出界度
- 是c++预处理器元编程图灵完备的
- 如何在C++中计算有向图直径
- 用于枚举完整图的哈密顿循环的算法(循环、反向、环绕或重复不计算在内的排列)
- 位图行大小计算
- C++模板图灵完成