Reputation: 4473
Consider this code snippet:
#include <iostream>
struct A {
void f() { std::cout << "f"; }
void g() { std::cout << "g"; }
template <bool b>
void call() { (b ? f() : g()); }
};
int main()
{
A().call<true>();
}
Depending on the template
paramter passed to call
, either f
or g
will be called. My question is, if the compiler is somehow forced to pre-evaluate the if condition. Consider this other possible implementation of call
:
template <bool b>
void call() {
bool x = b;
(x ? f() : g());
}
In this case, the compile-time template is first converted into a runtime variable, before the decision on f
or g
is made. I would assume, that the compiler would not be able to remove the if statement in this case.
Indeed, if I test this behaviour with godbolt that seems to be exactly what happens.
Is there some part of the standard that defines which template expressions have to be evaluated at compile-time?
(Of course, in this simple example, I could easily write specializations for b == true
and b == false
, but that is not what this question is about.)
Upvotes: 1
Views: 87
Reputation: 11350
All template expressions are evaluated at compile time, because templates don't exist at runtime. You can use if constexpr
which is garantueed to be evaluated at compile time:
template <bool b>
void call() { if constexpr (b) f(); else g(); }
In you example (for b = true
) this will become
void call() { f(); }
regardless of optimization level.
However when you use a normal if
or a ternary operator the generated code might be easily optimized. In your example (again for b=true
) template instantion creates something like this:
void call() { (true ? f() : g()); }
which the compiler can easily optimize if you allow him to. G++ with -O3
for example just removes the instantion of A
and the call to call
alltogether and just moves std::cout << "f"
into main
. See on godbolt.
Concolusion: All template expressions are evaluated at compile time, but the compiler can recognize if an expression or variable is constant and is able to optimize such cases, but the compiler is not obliged to do so (you don't want optimized code when you try to debug something)
Upvotes: 2