Is it possible to test if a constexpr function is evaluated at compile time?

前端 未结 6 1966
长情又很酷
长情又很酷 2020-12-14 07:02

Since the extended versions of constexpr (I think from C++14) you can declare constexpr functions that could be used as "real" cons

6条回答
  •  太阳男子
    2020-12-14 07:30

    The technique listed works, but since it uses static_assert it is not sfinae friendly. A better way (in theory, you'll see what I mean) to do this is to check whether a function is noexcept. Why? Because, constant expressions are always noexcept, even if the functions are not marked as such. So, consider the following code:

    template 
    constexpr void test_helper(T&&) {}
    
    #define IS_CONSTEXPR(...) noexcept(test_helper(__VA_ARGS__))
    

    test_helper is constexpr, so it will be a constant expression as long as its argument is. If it's a constant expression, it will be noexcept, but otherwise it won't be (since it isn't marked as such).

    So now let's define this:

    double bar(double x) { return x; }
    
    constexpr double foo(double x, bool b) {
        if (b) return x; 
        else return bar(x);
    }
    

    foo is only noexcept if the x is a constant expression, and b is true; if the boolean is false then we call a non constexpr function, ruining our constexpr-ness. So, let's test this:

    double d = 0.0;
    
    constexpr auto x = IS_CONSTEXPR(foo(3.0, true));
    constexpr auto y = IS_CONSTEXPR(foo(3.0, false));
    constexpr auto z = IS_CONSTEXPR(foo(d, true));
    
    std::cerr << x << y << z;
    

    It compiles, great! This gives us compile time booleans (not compile failures), which can be used for sfinae, for example.

    The catch? Well, clang has a multi-year bug, and doesn't handle this correctly. gcc however, does. Live example: http://coliru.stacked-crooked.com/a/e7b037932c358149. It prints "100", as it should.

提交回复
热议问题