Reputation: 2553
With normal if
condition, short circuiting works.
However with an attempted short circuit for if-constexpr doesn't work:
#include <iostream>
template <typename ... Args>
void foo(Args... args) {
std::string a;
// for the call of foo, sizeof...(args) = 0, so a > 2 shouldn't be evaluated.
if constexpr (sizeof...(args) == 0 || a > 2) {
std::cout << "ASD" << '\n';
}
}
int main() {
foo();
}
Edit: Seems like lots of comments are bit off of what I was attempting. I will just quote @chris comment:
People seem to be missing the point, so here's a better example of why this is useful:
if constexpr (sizeof...(Ts) > 0 && is_integral_v<first_t<Ts...>>) { /* corresponding logic */ }
Currently, this requires nested constexpr ifs
It seems this is not currently possible and only workaround is just write nested ifs.
Upvotes: 8
Views: 1304
Reputation: 170
You can use short-circuit form in if constexpr
, but please notice, this may performs differently with runtime if
. Consider the following example:
#include <type_traits>
template<typename T>
constexpr auto foo(T const& val)
{
if constexpr (std::is_integral_v<T>)
{
if constexpr (T{} < 1)
return val * 2;
}
return val;
}
template<typename T>
constexpr auto bar(T const& val)
{
if constexpr (std::is_integral_v<T> && T{} < 1)
return val * 2;
else
return val;
}
int main()
{
constexpr char const* x = "hello";
static_assert(foo(5) == 5 * 2);
static_assert(foo(x) == x);
static_assert(bar(5) == 5 * 2);
//static_assert(bar(x) == x); // ERROR, not compile
return 0;
}
The foo
will compile with both int
and char const*
while bar
not, and because std::is_integral_v<T> && T{} < 1
in bar
is instantiated as a whole.
So you'd better NOT short-circuit if constexpr
to avoid this unexpected behavior.
Upvotes: 0
Reputation:
The expression a > 2
needs to be syntactically and semantically valid, because otherwise, the compiler cannot rule out that it would return some type for which the ||
operator is overloaded. Only the built-in ||
operator has short-circuiting behaviour.
However, the expression a > 2
would not be evaluated. You can verify this by changing std::string a
to int a
(left uninitialised): evaluation of the expression a > 2
would have undefined behaviour, and therefore evaluation of a > 2
is not permitted in constant expressions.
Upvotes: 5
Reputation: 7983
While the condition might not be evaluated, your program doesn't compile because it is invalid – you can't compare a string
and an int
. You would get similar results if you put random characters in the second operand of the ||
.
Upvotes: 4