Inspired by this answer, I tried to copy and paste (and add testing in main()
) this code:
template<typename T>
std::tuple<int, double> foo(T a) {
if constexpr (std::is_same_v<int, T>)
return {a, 0.0};
else if (std::is_same_v<double, T>)
return {0, a};
else
return {0, 0.0};
}
int main() {
auto [x, y] = foo("");
std::cout << x << " " << y;
}
This is very straightforward - if T
is deduced as int
, we want to return a tuple of [a, 0.0]
. If T
is deduced as double
, we want to return a tuple of [0, a]
. Otherwise, we want to return [0, 0.0]
.
As you can see, in the main()
function, I am calling foo
with const char*
argument, which should result in x
and y
being 0
. That is not the case.
While trying to compile it, I encountered a strange error:
error: could not convert '
{0, a}
' from '<brace-enclosed initializer list>
' to 'std::tuple<int, double>
'
And I was like what?. Why on earth would I want that... I specifically used std::is_same
to enable return {0, a}
only when the type of a
is deduced as double
.
So I quickly ran to cppreference on if-constexpr. At the bottom of the page, above Notes, we can see this snippet of code:
extern int x; // no definition of x required
int f() {
if constexpr (true)
return 0;
else if (x)
return x;
else
return -x;
}
I thought to myself oookay..? I can't really see what's wrong with the original code. They use the same syntax and semantics....
But I was curious. I was curious if maybe something odd (at that time) might fix that issue, so I changed the original code to:
template<typename T>
std::tuple<int, double> foo(T a) {
if constexpr (std::is_same_v<int, T>)
return {a, 0.0};
else if constexpr (std::is_same_v<double, T>) // notice the additional constexpr here
return {0, a};
else
return {0, 0.0};
}
int main() {
auto [x, y] = foo("");
std::cout << x << " " << y;
}
And voilà! The code compiled and executed as expected. So, my question is - Do we need to put constexpr
after every if
statement in if-else
statement in these kind of situations? Or is it just my compiler? I am using GCC 7.3.