【问题标题】:Can I make expressions constexpr?我可以制作表达式 constexpr 吗?
【发布时间】:2020-12-17 14:29:27
【问题描述】:

我最近编写了一些代码,将函数结果打印到cout。结果本可以在编译时进行评估,但事实并非如此:

#include <algorithm>
#include <iostream>

constexpr unsigned int gcd(unsigned int u, unsigned int v)
{
    // ...
}

int main() {
    std::cout << gcd(5, 3) << std::endl;
}

无论出于什么奇怪的原因,它都会编译为:(clang -O3 -std=c++17)

main:
    push    r14
    push    rbx
    push    rax
    mov     edi, 5
    mov     esi, 3
    call    gcd(unsigned int, unsigned int)
    mov     esi, eax
    ...

请参阅Compiler Explorer 以获取实时示例。

我希望编译器在编译时评估gcd(5, 3),以避免在运行时浪费周期,这显然是可能的。我知道我可以做到以下几点:

int main() {
    constexpr unsigned g = gcd(5, 3); 
    std::cout << g << std::endl;
}

但是,这是不必要的冗长。我想做的就是这样:

#define CONSTEVAL(expression) // ...

int main() {
    std::cout << CONSTEVAL(gcd(5, 3)) << std::endl;
}

是否存在任何类型的编译器可以使CONSTEVAL 宏成为可能?或者更好 - 完全便携的东西?

【问题讨论】:

    标签: c++ macros c++17 constexpr compile-time


    【解决方案1】:

    立即调用的 lambda 表达式怎么样?

    #define CONSTEVAL(...) []{ constexpr auto result = __VA_ARGS__; return result; }()
    

    这实际上是一种生成constexpr 变量以保存结果并计算变量值的方法。


    这也可以通过模板进行无宏操作,但前提是值可以作为模板参数传递:

    template <auto V>
    inline constexpr auto consteval_v = V;
    

    用作consteval_v&lt;gcd(5, 3)&gt;

    【讨论】:

    • 不错。这必须是一个宏吗?
    • 那行得通。为什么要使用__VA_ARGS__?保留逗号还是什么?
    • @J.Schultke 没错。例如,CONSTEVAL(some_template_function&lt;5, 3&gt;(1)) 否则将无法正常工作。
    • @cigien 事实上,它没有。如果 constexpr 值可以作为模板参数传递,我们可以使用模板。但是,这不太通用,因为并非每个 constexpr 值都可以作为模板参数传递(例如,我认为浮点数是一个例外)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 2010-09-29
    • 2014-12-10
    • 1970-01-01
    • 2013-01-17
    • 2020-03-16
    相关资源
    最近更新 更多