简体   繁体   English

强制在编译期间评估常量表达式?

[英]Forcing a constant expression to be evaluated during compile-time?

A few days ago I asked by which criteria the compiler decides whether or not, to compute a constexpr function during compile time. 几天前,我询问编译器决定是否在编译期间计算constexpr函数。

When does a constexpr function get evaluated at compile time? 什么时候constexpr函数在编译时得到评估?

As it turns out, a constexpr is only evaluated during compile-time, if all parameters are constant expressions and the variable you are assigning it to is are constant expression as well. 事实证明,只有在编译时才会评估constexpr,如果所有参数都是常量表达式,并且您指定给它的变量也是常量表达式。

template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
    return (expo != 0 )? base * POW(base, expo -1) : 1;
}

template<typename T>
void foobar(T val)
{
    std::cout << val << std::endl;
}

int main(int argc, char** argv)
{
    foobar(POW((unsigned long long)2, 63));
    return 0;
}

If what I was told is true, this code example is very impratical, since foobar doesn't take a constexpr (you can't use consexpr for parameters for some reason), POW gets evaluated during runtime, even though it would have been possible to compute it during compile-time. 如果我被告知是真的,这个代码示例是非常不实际的,因为foobar不接受constexpr(由于某种原因你不能使用consexpr作为参数),POW在运行时被评估,即使它可能是可能的在编译期间计算它。 The obvious solution for forcing a compile-time evaluation would be this: 强制编译时评估的明显解决方案是:

auto expr = POW((unsigned long long)2, 63);
foobar(expr);

This however forces me to use an additional line of code, which shouldn't be necessary each time I want to make sure a constexpr gets evaluated during compile-time. 然而,这迫使我使用额外的代码行,每次我想确保在编译时评估constexpr时都不需要这样做。 To make this a little more convenient, I've come up with the following dubious macro: 为了使这更方便一点,我想出了以下可疑的宏:

#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
foobar(FORCE_CT_EVAL(POW((unsigned long long)2, 63)));

Despite the fact that it works just fine, I feel like as if something isn't right about it. 尽管它工作得很好,但我觉得好像有些不对劲。 Does creating an anonymous lambda impact performance? 创建匿名lambda会影响性能吗? Does returning by rvalue reference actually move the expression to the function parameter? 通过rvalue引用返回实际上是将表达式移动到函数参数吗? How does std::move impact performance? std :: move如何影响性能? Is there a better one liner solution for this? 有没有更好的单线解决方案呢?

Just to not leave it buried in comments: 只是不要把它埋在评论中:

#include <type_traits>

#define COMPILATION_EVAL(e) (std::integral_constant<decltype(e), e>::value)

constexpr int f(int i){return i;}

int main()
{
    int x = COMPILATION_EVAL(f(0));
}

EDIT1: EDIT1:

One caveat with this approach, constexpr functions can accept floating-point and be assigned to constexpr floating-point variables, but you cannot use a floating-point type as a non-type template parameter. 使用这种方法的一个警告是, constexpr函数可以接受浮点并分配给constexpr浮点变量,但是不能将浮点类型用作非类型模板参数。 Also, same limitations for other kinds of literals. 此外,对其他种类的文字也有同样的限制。

Your lambda would work for that, but I guess you would need a default-capture to get meaningful error message when non- constexpr stuff get passed to the function. 你的lambda会为此工作,但我猜你需要一个默认捕获来获得有意义的错误消息,当非constexpr东西传递给函数时。 That ending std::move is dispensable. 结束std::move是可有可无的。

EDIT2: EDIT2:

Err, your lambda approach doesn't work for me, I just realized, how it can even work, the lambda is not a constexpr function. 呃,你的lambda方法对我不起作用,我刚才意识到,它甚至可以工作,lambda不是constexpr函数。 It should not be working for you too. 它也不适合你。

It seems there's really no way around it but initializing a constexpr variable in local scope. 似乎没有办法解决它,但在本地范围内初始化constexpr变量。

EDIT3: EDIT3:

Oh, ok, my bad, the purpose of the lambda is just the evaluation. 哦,好吧,我的坏,lambda的目的只是评价。 So it's working for that. 所以它正在努力。 Its result, instead, is which is unusable to follow another compilation time eval. 相反,它的结果是无法跟随另一个编译时间eval。

EDIT4: EDIT4:

On C++17, lambdas now can be used in constexpr contexts , so the limitation referred to in EDIT2/EDIT3 is removed! 在C ++ 17上, lambdas现在可以在constexpr上下文中使用 ,因此删除了EDIT2 / EDIT3中引用的限制! So the lambda solution is the correct one. 所以lambda解决方案是正确的。 See this comment for more information. 有关更多信息, 请参阅此评论

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM