有没有办法在编译时间和运行时间之间对函数进行专门化?
使用constexpr
,函数可以在编译时或运行时根据参数进行评估。 但通常,编译时间和运行时间之间的算法必须不同。 例如。 考虑factorte的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
也是尽可能高效。
不,据我所知,您无法检测到编译器在给定调用中如何使用该函数,或者指示编译器根据常量使用不同的实现。
但首先, constexpr
函数仅限于单个return
语句,这意味着编译器可以(通常)轻松应用尾递归优化,将递归调用转换为循环。 因此,这个问题是关于如何做过早优化 ,这不是一个好主意。 低级优化是编译器的工作:让它。
其次,如果你确实想做编译器的工作,那么你可以命名这些函数,而不是试图无意识地将两个不同的函数实现塞进一个函数。 为了什么目的? 只有默默无闻。
对于给出的具体例子,
constexpr int fact(int n)
{
return (n)?n*fact(n-1):1;
}
编译器必须认识到它可以重写为尾递归。 正如我从我的早期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 );
}
免责声明:代码没有被编译器的脏手触及。
链接地址: http://www.djcxy.com/p/11723.html上一篇: Is there a way to specialize a function between compile time and run time?
下一篇: library to detect overlapping communities in a network?