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

3 Answers 3

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);
}
Sign up to request clarification or add additional context in comments.

1 Comment

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

4 Comments

Actually, the first one is guaranteed to be evaluated at run-time.
@cigien Is it somehow exempt from the as-if rule?
@HolyBlackCat No, the program must still behave as-if the call was constant evaluated. I'll try and write an answer.
@cigien - Do you mean the foo() call in doSomething(foo(4))? Are you sure?
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.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.