Trivia impact: rare
The Branch That Does Not Exist
an impossible member access, and a well-formed call
template <class T>
void show(T value) {
if constexpr (std::is_integral_v<T>) {
std::cout << value + 1 << '\n';
} else {
std::cout << value.name() << '\n';
}
}
show(41);
Does int need a name() member for this to compile?
Why¶
The if constexpr condition is true for int, so [stmt.if] discards the else statement
while instantiating show<int>. The member access is dependent on T, which postpones its
checking until that point; the discarded statement is not instantiated. A non-dependent
error in that branch would still be rejected even if the condition were false.
Where it shows up¶
Generic functions use this to choose operations supported by different categories of types without an overload for every case. The exemption for ill-formed dependent code is template-specific; outside a templated entity, discarded code is still checked.
Takeaway: A dependent branch discarded by if constexpr need not be well-formed.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo