强制在编译期间评估常量表达式? [英] Forcing a constant expression to be evaluated during compile-time?

查看:167
本文介绍了强制在编译期间评估常量表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几天前,我问编译器决定是否在编译时计算一个constexpr函数。

A few days ago I asked by which criteria the compiler decides whether or not, to compute a constexpr function during compile time.

constexpr函数在编译时是否得到求值?

事实证明,只有在编译期间,如果所有的参数都是常量表达式,并且赋给它的变量也是常量表达式,那么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.

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;
}

如果我被告知是真的,这个代码示例是非常不合理的,因为foob​​ar不接受constexpr(由于某种原因,你不能使用consexpr参数),POW在运行时被评估,即使它可能在编译期间计算。强制编译时评估的明显解决方案是:

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. The obvious solution for forcing a compile-time evaluation would be this:

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

然而,这迫使我使用额外的一行代码,想要确保一个constexpr在编译期间被评估。为了使这一点更方便,我想出了以下可疑的宏:

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. 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)));

尽管事实上它很好,但我觉得有些事情是不对的。是否创建匿名lambda影响性能?是否通过右值引用返回实际上将表达式移动到函数参数? std :: move如何影响性能?是否有更好的一个衬垫解决方案?

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? Does returning by rvalue reference actually move the expression to the function parameter? How does std::move impact performance? 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:



使用这种方法的一个警告是, constexpr 函数可以接受浮点数,并分配给 constexpr 浮点变量,但不能将浮点类型用作非类型模板参数。

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. Also, same limitations for other kinds of literals.

你的lambda将会工作,但我想你需要一个默认捕获来获得有意义的错误消息, constexpr 将东西传递给函数。 std :: move 是不必要的。

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. That ending std::move is dispensable.

Err,你的lambda方法不适用于我,我只是意识到,它甚至可以工作,lambda不是一个 constexpr 函数。它不应该为你工作。

Err, your lambda approach doesn't work for me, I just realized, how it can even work, the lambda is not a constexpr function. It should not be working for you too.

似乎没有办法,但初始化一个 constexpr 变量

It seems there's really no way around it but initializing a constexpr variable in local scope.

哦,好吧,不好,lambda的目的只是评价。所以它的工作。它的结果,而不是不能使用另一个编译时间eval。

Oh, ok, my bad, the purpose of the lambda is just the evaluation. So it's working for that. Its result, instead, is which is unusable to follow another compilation time eval.

这篇关于强制在编译期间评估常量表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆