decltype of ternary operator is different in MSVC ~C++17

Viewed 127

std::common_reference uses decltype to the ternary operator ?:

Otherwise, if decltype(false? val<T1>() : val<T2>()), where val is a function template template<class T> T val();, is a valid type, then the member type type names that type;

But MSVC says decltype(false? val<int&&>() : val<int&&>()) is int in the below code in below C++20.

#include <type_traits>

template<typename T>
T val();

int main() {
    static_assert(std::is_same<int&&, decltype(val<int&&>())>::value, "1");
    static_assert(std::is_same<int&&, decltype(false?val<int&&>():val<int&&>())>::value, "2");
}

https://godbolt.org/z/KE9PnGvd5

What is a correct behavior?

Is this an MSVC defect?

1 Answers

This is an MSVC bug.

The rules for the conditional operator are in [expr.cond]. There are many parts of those rules that are quite complex, but this case is actually the easy one:

If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.

That's our case: we have two int&&s, which are glvalues of the same value category and the same type - so the result is also int&&.

Related