Is it possible for the template parameter to be a reference type?
They are both right :
See the code generated in cppinsights
template<typename T1, typename T2>
auto max(T1 a, T2 b) -> decltype(b<a?a:b) {
return b < a ? a : b;
}
template<typename T1, typename T2>
auto max2(T1 a, T2 b){
return b < a ? a : b;
}
max(j,i);
max2(j,i);
Will 'generate' :
template<>
int & max<int, int>(int a, int b)
{
return b < a ? a : b;
}
template<>
int max2<int, int>(int a, int b)
{
return b < a ? a : b;
}
The trouble is about C++11 -> decltype(b<a?a:b)
if you remove it (in C++14 and more) the function will not return a reference anymore
static_assert( is_same_v<decltype(i),int> );
static_assert( is_same_v<decltype((i)),int&> );
static_assert( is_same_v<decltype(i+j),int> );
static_assert( is_same_v<decltype(true?i:j),int&> );
See https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator
4) If E2 and E3 are glvalues of the same type and the same value category, then the result has the same type and value category [...]
5) Otherwise, the result is a prvalue [...]
In C++ that mean :
static_assert( is_same_v<decltype(true?i:j),int&> ); // E2 and E3 are glvalues
static_assert( is_same_v<decltype(true?i:1),int> ); // Otherwise, the result is a prvalue