Recently I modify some if constexpr
into if
in my constexpr functions and found they still work fine and can be evaluated when compile time. Here is a minimum case:
template<int N>
constexpr bool is_negative()
{
if constexpr (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
live demo
In the case above, N
must be known at compile time because it is non-type template parameter, so if constexpr
works fine here. However, it is a constexpr function, so, iirc, it is possible to get a return value even though I replace if constexpr
with if
:
template<int N>
constexpr bool is_negative()
{
if (N >= 0) return false;
else return true;
}
int main()
{
constexpr bool v = is_negative<1>();
}
live demo
From cppref, all of the requirements in A constexpr function must satisfy the following requirements:
don't mention if
. So, IIUC, it should be implementation defined behavior whether constexpr function contain if
to be evaluted at compile time even though all related variable is known at compile time(like is_negative
above).
So, my conclusion is:
if constexpr
, so the choice is if
, which means it is not guaranteed to get our constexpr functions get evaluted at compile time, all depend on compiler implementationif constexpr
is preferred if we want constexpr functions get evaluated at compile time.All above is my personal thoughts, maybe something important missed/misunderstand, feel free to correct me. The question is still unchanged: if
and if constexpr
, which should be prefered for constexpr functions which expected to be evaluated at compile time.
references: - What is Allowed in a constexpr Function? - Difference between "if constexpr()" Vs "if()"
Before c++17, we don't have if constexpr, so the choice is if, which means it is not guaranteed to get our constexpr functions get evaluted at compile time, all depend on compiler implementation
The fact that an if statement is not constexpr does not mean it can't be evaluated at compile time, as part of a constexpr expression. In your example, v
is evaluated at compile time in both cases, because it is required to be: it's a constant expression. That's not implementation defined.
After c++17, if constexpr is prefered if we want constexpr functions get evaluated at compile time.
Constexpr if statements were introduced to solve a problem. Getting constexpr functions to get evaluated at compile time is not that problem.
Here is an example where a constexpr if
is required instead of a simple if
(taken from cppreference):
template <typename T>
auto get_value(T t) {
if constexpr(std::is_pointer_v<T>)
return *t; // deduces return type to int for T = int*
else
return t; // deduces return type to int for T = int
}
Try removing the constexpr
keyword and see what happens (demo).
Also, note that you can always solve that problem using other methods, but if constexpr
has the advantage of conciseness. For instance, here's an equivalent get_value
using tag dispatching:
template<typename T>
auto get_value_impl(T t, std::true_type) {
return *t;
}
template<typename T>
auto get_value_impl(T t, std::false_type) {
return t;
}
template<typename T>
auto get_value(T t) {
return get_value_impl(t, std::is_pointer<T>{});
}
Demo
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