openframeworks / openFrameworks

openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
Other
9.84k stars 2.56k forks source link

universal/resilient ofMin/Max #7940

Closed artificiel closed 1 month ago

artificiel commented 2 months ago

from #7918

the idea is to prevent conversion to float with ofMin/Max (and maybe applicable to other) for the benefit of end users that mix/match types (typically floats (as returned by many OF functions), double (as dotted-decimals are interpreted in C++ source code) and int, also as textual interpretations).

comparing different types is not evident, especially when unsigned is thrown in (I guess that's why std::min does not attempt it, but our use case is probably defined enough to tackle in a specific way).

the logic:

template<typename T, typename Q> auto ofMin(const T & t, const Q & q) const { using CommonType = typename std::common_type<T, Q>::type; if constexpr ((std::is_same_v<T, uint64_t> or std::is_same_v<T, size_t>) && std::is_signed_v) { if (q < 0) { return q; } else { return std::min(static_cast(t), q); } } else if constexpr ((std::is_same_v<Q, uint64_t> or std::is_same_v<Q, size_t>) && std::is_signed_v) { if (t < 0) { return t; } else { return std::min(t, static_cast(q)); } } else if constexpr (std::is_signed_v && std::is_unsigned_v) { if (t < 0 || q > static_cast(std::numeric_limits::max())) { return static_cast(t); } else { return std::min(static_cast(t), static_cast(q)); } } else if constexpr (std::is_signed_v && std::is_unsigned_v){ if (q < 0 || t > static_cast(std::numeric_limits::max())) { return static_cast(q); } else { return std::min(static_cast(t), static_cast(q)); } } else { return std::min(static_cast(t), static_cast(q)); } }

ofTheo commented 2 months ago

looks good to me! thanks @artificiel