#include <iostream>
#include <type_traits>
#include <boost/type_traits.hpp>
template<typename T, typename U>
struct promote
{
private:
typedef typename std::conditional<(sizeof(T) > sizeof(U)), T, U>::type Bigger;
typedef typename std::add_const<Bigger>::type BConst;
public:
//because mingw4.6.2 do not implement std::add_reference
typedef typename boost::add_reference<BConst>::type type;
};
template<typename T, typename U>
auto max(T const &a, U const &b)->typename promote<T, U>::type
{
return a > b ? a : b;
}
int main(int argc, char *argv[])
{
std::cout<<max(3, 4.5)<<std::endl;
std::cout<<max(4.5, 3)<<std::endl;
return 0;
}
std::max of mingw4.6.2
template<typename T>
inline T const& max(T const &a, T const &b)
{
return a > b ? a : b;
}
This will give me warning messages
main.cpp:27:24: warning: returning reference to temporary [enabled by default]
main.cpp:27:24: warning: returning reference to temporary [enabled by default]
Compiler is migw4.6.2, OS is win7 64bits
second version, only support scalar type
template<typename T, typename U>
struct promote
{
typedef typename std::conditional<(sizeof(T) > sizeof(U)), T, U>::type type;
};
template<typename T, typename U>
inline typename promote<T, U>::type max(T a, U b)
{
static_assert(std::is_scalar<T>::value, "inhomogeneous max only support scalar type");
static_assert(std::is_scalar<U>::value, "inhomogeneous max only support scalar type");
return a > b ? a : b;
}
The other solution are using SFINAE and boost::mpl to do some “overload”.
I think I would just explicitly name the type of std::max in the real case
No, it’s not safe. That’s exactly what the compiler warns you about. You return reference to a temporary value (4.5 in this case). If you assign the result to something like
int &x = max(3, 4,5);,xwill become a dangling reference immediately after this line.