bal*_*lki 7 c++ constexpr c++11
使用constexpr,可以在编译时或运行时根据参数计算函数.但通常,算法必须在编译时和运行时之间有所不同.例如.考虑constexpr版本的factorial.
constexpr int fact(int n)
{
return (n)?n*fact(n-1):1;
}
Run Code Online (Sandbox Code Playgroud)
如果n在运行时发生,那么函数效率低于一个forloop?是否有一些模板魔术来确定函数是在编译时还是在运行时执行并使用不同的算法?
更新:
factorial只是一个例子.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);
}
Run Code Online (Sandbox Code Playgroud)
如果函数是在运行时编写的,那么它可以从Memoization中受益.即使这是可能的,我想很难表达这个功能,使其constexpr在运行时尽可能高效.
不,据我所知,您无法检测编译器如何在给定调用中使用该函数,也无法指示编译器根据常量使用不同的实现。
但首先,constexpr函数仅限于单个return语句,这意味着编译器(大多数情况下)可以轻松应用尾递归优化,将递归调用转变为循环。因此,这个问题是关于如何进行过早优化,这不是一个好主意。低级优化是编译器的工作:让它去做。
其次,如果你真的很想完成编译器的工作,那么你可以只命名函数,而不是试图毫无意义地将两个不同的函数实现塞进一个函数中。这样做的目的是什么?只有默默无闻。
对于给出的特定示例,
constexpr int fact(int n)
{
return (n)?n*fact(n-1):1;
}
Run Code Online (Sandbox Code Playgroud)
编译器必须认识到它可以重写为尾递归。正如我从我对早期 SO 问题的测试中回忆起的那样,即使是 Visual C++ 编译器也能做到这一点。尽管由于一些莫名其妙的原因(可能与原始的 x86 处理器设计有关),它被浮点类型的使用所困扰:相同的高级逻辑,不同的低级结果。
作为一项稍微不那么激烈的帮助编译器的工作,在测量并发现该函数使您的应用程序速度慢得令人无法接受之后,并且在检查了机器代码并发现编译器无法识别该函数的尾部之后,递归性,你可以重写如下:
constexpr int fact( int multiplier, int n )
{
return (n != 0? fact( multiplier*n, n-1 ) : multiplier);
}
constexpr int fact( int n )
{
return fact( 1, n );
}
Run Code Online (Sandbox Code Playgroud)
免责声明:代码没有被编译器的脏手触及。
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |