0

If I want to have a function that behaves the same as a macro, that is, compute the value at compile time, can I use a constexpr function?

For example, can I replace the Foo macro by the foo function and still have a compile time evaluated result in all of the following cases:

#define FOO(x) (x + 2)

constexpr int foo(int x) {
    return x + 2;
}

void doSomething(int a) { ... }

int main() {
    int res1 = foo(3);
    doSomething(foo(4));
    const int res2 = foo(5);
    return 0;
}
Jojolatino
  • 696
  • 5
  • 11
  • 1
    Does this answer your question? [When does a constexpr function get evaluated at compile time?](https://stackoverflow.com/questions/14248235/when-does-a-constexpr-function-get-evaluated-at-compile-time) – JaMiT Oct 30 '20 at 20:44
  • This can also be useful: https://stackoverflow.com/q/63637443/1896169 – Justin Oct 30 '20 at 21:04

3 Answers3

4

With C++20, consteval might be your friend here:

consteval int foo(int x) {
    return x + 2;
}

int main() {
    constexpr int r = foo(2);
}
plexando
  • 1,151
  • 6
  • 22
  • Is `constexpr` required in `constexpr int r = foo(2);`? If so, what's the point of using `consteval` instead of `constexpr` when defining `foo`? (I think the result would be the same if consteval is changed to constexpr in your example.) – starriet Dec 09 '22 at 00:53
3

By themselves, constexpr functions are not required to be evaluated at compile time. However, you can force them to be evaluated by assigning the return value to a constexpr variable:

doSomething(foo(4)); // foo(4) not guaranteed to be evaluated at compile time
constexpr auto result = foo(4); // foo(4) _is_ guaranteed to be evaluated at compile time
doSomething(result):

Also, a note about your question on macros. A macro definition has nothing to do with compile time evaluation. It's more akin to an always inline function.

Fatih BAKIR
  • 4,569
  • 1
  • 21
  • 27
3

It's impossible to detect if something was evaluated at runtime or compile-time using only the C++ itself, so the as-if rule allows the compiler to do whatever it wants.

Nothing stops a compiler from performing the addition in your macro at runtime, and nothing stops it from calculating even a non-constexpr function at compile-time (as long as it doesn't perform any IO, etc). It all depends on optimization settings and the sanity of the compiler.

Normally, in unoptimized builds, constexpr functions are executed at runtime unless the return value is used in a context that requires a compile-time constant. This includes initializing a constexpr variable from it, and your const int res2 implicitly becomes constexpr because its initializer is constexpr, so foo(5) should be called at compile-time.

In optimized builds, you can expect the compiler to do as much as possible at compile-time. (A function doesn't even have constexpr, as long as the function body is visible in the current translation unit, or if link-time optimizations are enabled.)

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207