1 #ifndef EAGINE_IS_WITHIN_LIMITS_HPP 
    9 #define EAGINE_IS_WITHIN_LIMITS_HPP 
   17 #include <type_traits> 
   21 #if defined(__clang__) 
   22 EAGINE_DIAG_OFF(shorten-64-to-32)
 
   23 #elif defined(__GNUC__) 
   24 EAGINE_DIAG_OFF(
sign-compare)
 
   29 template <
typename Dst, 
typename Src>
 
   30 struct implicitly_within_limits
 
   32       ((std::is_integral_v<Dst> && std::is_integral_v<Src>) ||
 
   33        (std::is_floating_point_v<Dst> && std::is_floating_point_v<Src>)) &&
 
   34       (std::is_signed_v<Dst> ==
 
   35        std::is_signed_v<Src>)&&(sizeof(Dst) >= sizeof(Src)))> {};
 
   37 template <
typename Dst>
 
   38 struct implicitly_within_limits<Dst, bool> : std::is_integral<Dst> {};
 
   41 struct implicitly_within_limits<float, std::int16_t> : std::true_type {};
 
   44 struct implicitly_within_limits<float, std::int32_t> : std::true_type {};
 
   47 struct implicitly_within_limits<double, std::int16_t> : std::true_type {};
 
   50 struct implicitly_within_limits<double, std::int32_t> : std::true_type {};
 
   53 struct implicitly_within_limits<double, std::int64_t> : std::true_type {};
 
   62 struct within_limits_num {
 
   63     static constexpr 
auto check(Src) noexcept {
 
   64         return implicitly_within_limits<Dst, Src>::value;
 
   68 template <
typename Dst, 
typename Src, 
bool IsInt, 
bool IsSig>
 
   69 struct within_limits_num<Dst, Src, IsInt, IsInt, IsSig, IsSig> {
 
   70     static constexpr 
auto check(Src value) noexcept {
 
   71         using dnl = std::numeric_limits<Dst>;
 
   73         return (dnl::min() <= value) && (value <= dnl::max());
 
   77 template <
typename Dst, 
typename Src, 
bool IsInt>
 
   78 struct within_limits_num<Dst, Src, IsInt, IsInt, false, true> {
 
   79     static constexpr 
auto check(Src value) noexcept {
 
   80         using Dnl = std::numeric_limits<Dst>;
 
   81         using Tmp = std::make_unsigned_t<Src>;
 
   83         return (value < Src(0)) ? false : (Tmp(value) < Dnl::max());
 
   87 template <
typename Dst, 
typename Src, 
bool IsInt>
 
   88 struct within_limits_num<Dst, Src, IsInt, IsInt, true, false> {
 
   89     static constexpr 
auto check(Src value) noexcept {
 
   90         using dnl = std::numeric_limits<Dst>;
 
   92         return (value < dnl::max());
 
   96 template <
typename Dst, 
typename Src>
 
  101       std::is_integral_v<Dst>,
 
  102       std::is_integral_v<Src>,
 
  103       std::is_signed_v<Dst>,
 
  104       std::is_signed_v<Src>> {};
 
  106 template <
typename T>
 
  107 struct within_limits<T, T> {
 
  108     static constexpr 
auto check(T&) noexcept {
 
  121 template <
typename Dst, 
typename Src>
 
  123     return implicitly_within_limits<Dst, Src>::value ||
 
  124            within_limits<Dst, Src>::check(value);
 
  132 template <
typename Dst, 
typename Src>
 
  134   -> std::enable_if_t<std::is_convertible_v<Src, Dst>, Dst> {
 
  135     return EAGINE_CONSTEXPR_ASSERT(
 
  136       is_within_limits<Dst>(value), Dst(std::move(value)));
 
  143 template <
typename Dst, 
typename Src>
 
  147     if(is_within_limits<Dst>(value)) {
 
  148         return {Dst(std::move(value)), 
true};
 
  157 #endif // EAGINE_IS_WITHIN_LIMITS_HPP