Is it possible to know when is constexpr really a constexpr?

Since the extended versions of constexpr (I think from C++14) you can declare constexpr functions that could be used as "real" constexpr, that is, the code executed at compile time or can behave as inline functions. So when can have this program:

#include <iostream>

constexpr int foo(const int s) {
  return s + 4;
}

int main()
{
    std::cout << foo(3) << std::endl;
    const int bar = 3;
    std::cout << foo(bar) << std::endl;
    constexpr int a = 3;
    std::cout << foo(a) << std::endl;

    return 0;
}

Of course, the result is:

7
7
7

so far so good. So my question is: is there a way (possibly standard) to know in foo(const int s) if the function is beeing executed at compile time or at runtime?

EDIT: Also is it possible to know at runtime if a function was evaluated at compile time?


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 <class T>
constexpr void test_helper(T&& 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.


I think the canonical way to do that is with static_assert . static_assert s are evaluated at compile time, so they will break the build if their condition is false.

#include <iostream>

constexpr int foo(const int s) {
  return s + 4;
}

int main()
{
    std::cout << foo(3) << std::endl;
    const int bar = 3;
    std::cout << foo(bar) << std::endl;
    constexpr int a = 3;
    std::cout << foo(a) << std::endl;

    static_assert(foo(3) == 7, "Literal failed");
    static_assert(foo(bar) == 7, "const int failed");
    static_assert(foo(a) == 7, "constexpr int failed");
    return 0;
}

clang++ -std=c++14 so1.cpp compiles fine for me, showing that everything works as expected.


Within a constexpr function, you cannot tell if you are being evaluated in a constexpr context. There have been a number of proposals to add this functionality. None have succeeded.


Outside a constexpr function, there are a number of ways to determine if a call to a function with a certain set of arguments would be evaluated in a constexpr context. The easiest would be to use the result in a context requiring constexpr .

Assuming your constexpr expression returns a non-void integral or pointer type (including function pointer):

#define CONSTEXPR_EVAL(...) 
  std::integral_constant< 
    std::decay_t<decltype(__VA_ARGS__)>, 
    __VA_ARGS__ 
  >::value

then CONSTEXPR_EVAL( bar(foo, true) ) will fail to compile if bar(foo, true) cannot be evaluated at compile time, and if it can be evaluated at compile time it returns that value.

Other tricks involving noexcept (a function evaluated at compile time is noexcept ) can work (see @NirFriedman's answer).

链接地址: http://www.djcxy.com/p/68372.html

上一篇: UIImagePickerController释放我的视图和控制器

下一篇: 有没有可能知道何时constexpr真的是一个constexpr?