14

c++ 模板元编程是函数式编程的一种形式吗?如果是,是否存在一些陷阱,例如与 c++ 模板元编程相关的非尾递归的 stackoverflow?

对于这个问题中的阶乘模板示例,我猜它是标准的函数式编程。还是相似只是表面现象?

#include <iostream>
using namespace std;

template< int n >
struct factorial { enum { ret = factorial< n - 1 >::ret * n }; };

template<>
struct factorial< 0 > { enum { ret = 1 }; };

int main() {
    cout << "7! = " << factorial< 7 >::ret << endl; // 5040
    return 0;
}
4

3 回答 3

9

c++ 模板元编程是函数式编程的一种形式吗?

是的!模板扩展没有副作用,所以它是纯函数式的。

如果是,是否存在一些陷阱,例如与 c++ 模板元编程相关的非尾递归的 stackoverflow?

绝对地。阶乘并不是一个很好的证明,因为结果会在你的堆栈溢出之前很久,但是长递归肯定会导致编译器出错。然而,有趣的是,编译器倾向于以这样一种方式实现模板,即您可以获得自动记忆。例如,斐波那契数列的简单编写实现倾向于在 O(n) 时间而不是 O(2^n) 时间内编译。

于 2017-03-10T12:39:58.790 回答
7

我认为最好的答案是这两个概念是完全不同的东西。然而,这并没有真正的帮助,所以这里有一些我能想到的关键点:

  • C++ 模板和 ML 等函数式语言(参数多态性)都是泛型编程的示例,因此在一个问题中一起提及它们是有意义的。在学术界,甚至还有关于通用编程的研讨会,通常涵盖 C++ 模板内容和 ML 风格的函数式编程。

  • 但是,模板元编程为您提供了一种编写代码的方法,该代码在 C++ 代码编译期间得到“评估”,因此您只能将其用于非常有限的任务。另一方面,函数式程序通常在运行时运行,您可以定义复杂的数据结构、构建抽象等(您可以使用模板元编程来做一些事情,但它看起来很难看)。

  • 为什么阶乘示例类似于函数式编程中的阶乘?当您使用模板元编程时,您无法定义“可变变量”(因为您只是在定义新类型或模板),因此模板元编程可能感觉有点像函数式编程风格。

  • 使用模板元编程编写的代码在编译时进行评估。这意味着它不能依赖于用户输入!它要么编译,要么不编译(编译器可能对递归深度有一些限制,并在一段时间后放弃)。另一方面,函数式程序可以接受一些输入然后进行评估(这意味着它们可以使用所有可用的堆栈或内存然后失败)。

对于函数式程序员,我知道像Agda这样的一些函数式语言也可以在编译时评估事物,但我认为最好保持简单!

于 2012-07-12T23:32:01.720 回答
0

模板元编程在理论上是一种纯粹的面向函数的语言,即函数只依赖于它们的参数,而不考虑任何全局或局部状态。然而,我们似乎可以使用友元注入来捕获和检索元编程状态。因此,函数可以根据全局/局部元编程状态返回不同的结果。

于 2021-08-30T08:55:20.143 回答