【发布时间】:2013-01-18 07:55:41
【问题描述】:
使用constexpr,可以根据参数在编译时或运行时评估函数。但通常,编译时和运行时的算法必须不同。例如。考虑阶乘的 constexpr 版本。
constexpr int fact(int n)
{
return (n)?n*fact(n-1):1;
}
如果n 发生在运行时,该函数会不会比一个forloop 效率低?是否有一些模板魔术来确定函数是在编译时执行还是在运行时执行并使用不同的算法?
更新:
阶乘只是一个例子。如果在没有constexpr 限制的情况下进行编码,所有constexpr 函数是否都像它们一样高效?
例如:
constexpr int combinations(int n, int k)
{
//Assume all error conditions and edge conditions are taken care with ternary operator ?:
return fact(n)/(fact(k)*fact(n-k);
}
如果函数是在运行时编写的,它可以从Memoization 中受益。即使这是可能的,我想也很难将函数表达为既是constexpr,又是在运行时尽可能高效。
【问题讨论】:
-
它不会回答你的问题,但是如果你的编译器针对尾递归进行了优化,这个函数就不会低效。
-
@Eduardo 由于函数不是尾递归,因此编译器需要在这里做更多的事情。但是,现代编译器可以在足够简单的情况下对此进行优化(OP 的示例将被优化)。
-
不,当前语言无法检查
constexpr函数何时执行 - 编译器可能会根据rand() % 2 == 0突发奇想决定是否在编译时评估函数 -或运行时(假设存在实际在编译时对其进行评估的先决条件)。 -
@Xeo:好吧,如果结果需要是编译时常量(模板参数,
static <built-in> const,...),那么您可以确保在编译时完成计算;显然这并不能回答这个问题。 -
@KonradRudolph:你是对的;它必须在调用后将结果乘以 n。谢谢指正。