constexpr auto digits = std::numeric_limits<T>::digits;
template<typename T, typename U, std::enable_if_t<std::is_unsigned<T>{}&& std::is_unsigned<U>{}&&!std::is_same<T, U>{}, int>=0>// unsigned, unsigned
constexpr auto min(T t, U u)
{
using result_t = std::conditional_t<digits<U>< digits<T>, U, T>;// kleinerer Typ
return u < t ?static_cast<result_t>(u):static_cast<result_t>(t);
}
template<typename T, typename U, std::enable_if_t<std::is_signed<T>{}&& std::is_signed<U>{}&&!std::is_same<T, U>{}, int>=0>// signed, signed
constexpr auto min(T t, U u)
{
using result_t = std::conditional_t<digits<T>< digits<U>, U, T>;// größerer Typ
return u < t ?static_cast<result_t>(u):static_cast<result_t>(t);
}
template<typename T, typename U, std::enable_if_t<std::is_unsigned<T>{}&& std::is_signed<U>{}, int>=0>// unsigned, signed
constexpr auto min(T t, U u)
{
using result_t = U;
return u <0||static_cast<std::make_unsigned_t<U>>(u)< t ?static_cast<result_t>(u):static_cast<result_t>(t);
}
template<typename T, typename U, std::enable_if_t<std::is_signed<T>{}&& std::is_unsigned<U>{}, int>=0>// signed, unsigned
constexpr auto min(T t, U u)
{
using result_t = T;
return t >0&& u <static_cast<std::make_unsigned_t<T>>(t)?static_cast<result_t>(u):static_cast<result_t>(t);
}
template<typename T, typename U, std::enable_if_t<std::is_unsigned<T>{}== std::is_unsigned<U>{}&&!std::is_same<T, U>{}, int>=0>// unsigned, unsigned oder signed, signed
constexpr auto max(T t, U u)
{
using result_t = std::conditional_t<digits<U>< digits<T>, U, T>;// größerer Typ
return u < t ?static_cast<result_t>(u):static_cast<result_t>(t);
}
template<typename T, typename U, std::enable_if_t<std::is_unsigned<T>{}&& std::is_signed<U>{}, int>=0>// unsigned, signed
constexpr auto max(T t, U u)
{
using result_t = std::conditional_t<digits<T>< digits<std::make_unsigned_t<U>>, std::make_unsigned_t<U>, T>;
return u >=0&& t <static_cast<std::make_unsigned_t<U>>(u)?static_cast<result_t>(u):static_cast<result_t>(t);
}
template<typename T, typename U, std::enable_if_t<std::is_signed<T>{}&& std::is_unsigned<U>{}, int>=0>// signed, unsigned
constexpr auto max(T t, U u)
{
using result_t = std::conditional_t<digits<U>< digits<std::make_unsigned_t<T>>, std::make_unsigned_t<T>, U>;
return t <0||static_cast<std::make_unsigned_t<T>>(t)< u ?static_cast<result_t>(u):static_cast<result_t>(t);
}
int main()
{
constexpr char c =1;
constexpr unsignedshort us =2;
constexpr int i =3;
constexpr longlong ll =4;
constexpr unsignedlonglong ull =5;
static_assert( min( c, us )==1, "");
static_assert( std::is_same<decltype(min( c, us )), char>{}, "");
static_assert( max( c, us )==2, "");
static_assert( std::is_same<decltype(max( c, us )), unsignedshort>{}, "");