I'm trying to write a class that is closely related to integers, and because of that I included a conversion constructor with the form
constexpr example::example(const int &n);
My question is: if I subsequently define the function
void foo(example n);
and I use it like this
foo(3);
in my code, is the integer literal 3
converted in an instance of example
at compile time?
If no, is there a way to obtain this behavior?
If yes, does that still happen if the constructor isn't explicitly declared as constexpr
?
The fact that the constructor is constexpr
does not force the computation to happen at compile time. It only means that the constructor is eligible to be used within both constant expressions and non-constant expressions.
If on the other hand you declare the constructor consteval
, then it means that only constant expressions are allowed to call that constructor. This in turn implies that every invocation of the constructor must be checked by the compiler to ensure that it is a constant expression (because, if it is not, the compiler must diagnose the violation). Since checking that something is a constant expression requires checking whether it contains any undefined behaviour, such checking is as difficult as actually evaluating the expression. Therefore, you can be assured that declaring a constructor (or any other function) consteval
will ensure that the function will not be called at runtime: the compiler is allowed to generate code to re-evaluate it at runtime, but there is no reason why it would do so. The downsides of this approach are that, first, it becomes impossible to use the constructor in a non-constant expression, and second, constant expression evaluation is much slower than runtime evaluation, and you have to decide whether the increased compile times are worth it.
If you leave the constructor as constexpr
then you can still force it to be called at compile time in particular instances by using a constexpr
variable:
constexpr example ex = 3; // evaluated at compile time
foo(ex);
This is a consequence of the fact that a constexpr
variable is only allowed to be initialized by a constant expression.
In addition to the answer by Brian Bi, it should be mentioned that compiler optimization may cause the evaluation to happen at compile time in your example.
Look at this compilation without optimization https://godbolt.org/z/EccGosc7n versus the same code compiled with -O3
: https://godbolt.org/z/Kz51x4acK.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With