maths: relax argument restrictions for min/max

This commit is contained in:
Danny Robson 2018-05-30 16:54:04 +10:00
parent 11a077f63d
commit 437b4267d3

View File

@ -22,6 +22,7 @@
// instead, just use cassert // instead, just use cassert
#include "types/traits.hpp" #include "types/traits.hpp"
#include "coord/traits.hpp"
#include "float.hpp" #include "float.hpp"
#include <algorithm> #include <algorithm>
@ -613,52 +614,35 @@ namespace util {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/// Variadic minimum /// Variadic minimum
// disable the single parameter version for non-arithmetic types so that
// min for coord types is unambiguous. allow pointers too because it
// doesn't add ambiguity and it simplifies some memory juggling.
template <
typename T,
typename = std::enable_if_t<
std::is_arithmetic_v<T> || std::is_pointer_v<T>, void
>
>
constexpr T
min (const T a)
{ return a; }
//-------------------------------------------------------------------------
template <typename T, typename U, typename ...Args> template <typename T, typename U, typename ...Args>
constexpr std::enable_if_t< constexpr std::enable_if_t<
std::is_unsigned<std::decay_t<T>>::value == std::is_unsigned<std::decay_t<U>>::value && !is_coord_v<T> && !is_coord_v<U>,
std::is_integral<std::decay_t<T>>::value == std::is_integral<std::decay_t<U>>::value,
std::common_type_t<T,U> std::common_type_t<T,U>
> >
min (const T a, const U b, Args ...args) min (const T a, const U b, Args ...args)
{ {
return min (a < b ? a : b, std::forward<Args> (args)...); if constexpr (sizeof... (args) > 0) {
return min (a < b ? a : b, std::forward<Args> (args)...);
} else {
return a < b ? a : b;
}
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/// Variadic maximum /// Variadic maximum
template <typename T>
constexpr std::enable_if_t<std::is_arithmetic_v<T> || std::is_pointer_v<T>, T>
max (const T a)
{ return a; }
//-------------------------------------------------------------------------
template <typename T, typename U, typename ...Args> template <typename T, typename U, typename ...Args>
constexpr std::enable_if_t< constexpr std::enable_if_t<
std::is_unsigned<std::decay_t<T>>::value == std::is_unsigned<std::decay_t<U>>::value && !is_coord_v<T> && !is_coord_v<U>,
std::is_integral<std::decay_t<T>>::value == std::is_integral<std::decay_t<U>>::value,
std::common_type_t<T,U> std::common_type_t<T,U>
> >
max (const T a, const U b, Args ...args) max (const T a, const U b, Args ...args)
{ {
return max (a > b ? a : b, std::forward<Args> (args)...); if constexpr (sizeof... (args) > 0) {
return max (a > b ? a : b, std::forward<Args> (args)...);
} else {
return a > b ? a : b;
}
} }