OGLplus  (0.59.0) a C++ wrapper for rendering APIs

is_within_limits.hpp
Go to the documentation of this file.
1 #ifndef EAGINE_IS_WITHIN_LIMITS_HPP
9 #define EAGINE_IS_WITHIN_LIMITS_HPP
10 
11 #include "assert.hpp"
12 #include "diagnostic.hpp"
13 #include "int_constant.hpp"
14 #include "valid_if/decl.hpp"
15 #include <cstdint>
16 #include <limits>
17 #include <type_traits>
18 #include <utility>
19 
20 EAGINE_DIAG_PUSH()
21 #if defined(__clang__)
22 EAGINE_DIAG_OFF(shorten-64-to-32)
23 #elif defined(__GNUC__)
24 EAGINE_DIAG_OFF(sign-compare)
25 #endif
26 
27 namespace eagine {
28 //------------------------------------------------------------------------------
29 template <typename Dst, typename Src>
30 struct implicitly_within_limits
31  : bool_constant<(
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)))> {};
36 
37 template <typename Dst>
38 struct implicitly_within_limits<Dst, bool> : std::is_integral<Dst> {};
39 
40 template <>
41 struct implicitly_within_limits<float, std::int16_t> : std::true_type {};
42 
43 template <>
44 struct implicitly_within_limits<float, std::int32_t> : std::true_type {};
45 
46 template <>
47 struct implicitly_within_limits<double, std::int16_t> : std::true_type {};
48 
49 template <>
50 struct implicitly_within_limits<double, std::int32_t> : std::true_type {};
51 
52 template <>
53 struct implicitly_within_limits<double, std::int64_t> : std::true_type {};
54 //------------------------------------------------------------------------------
55 template <
56  typename Dst,
57  typename Src,
58  bool DIsInt,
59  bool SIsInt,
60  bool DIsSig,
61  bool SIsSig>
62 struct within_limits_num {
63  static constexpr auto check(Src) noexcept {
64  return implicitly_within_limits<Dst, Src>::value;
65  }
66 };
67 //------------------------------------------------------------------------------
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>;
72 
73  return (dnl::min() <= value) && (value <= dnl::max());
74  }
75 };
76 //------------------------------------------------------------------------------
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>;
82 
83  return (value < Src(0)) ? false : (Tmp(value) < Dnl::max());
84  }
85 };
86 //------------------------------------------------------------------------------
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>;
91 
92  return (value < dnl::max());
93  }
94 };
95 //------------------------------------------------------------------------------
96 template <typename Dst, typename Src>
97 struct within_limits
98  : within_limits_num<
99  Dst,
100  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>> {};
105 //------------------------------------------------------------------------------
106 template <typename T>
107 struct within_limits<T, T> {
108  static constexpr auto check(T&) noexcept {
109  return true;
110  }
111 };
112 //------------------------------------------------------------------------------
121 template <typename Dst, typename Src>
122 static constexpr auto is_within_limits(Src value) noexcept {
123  return implicitly_within_limits<Dst, Src>::value ||
124  within_limits<Dst, Src>::check(value);
125 }
126 //------------------------------------------------------------------------------
132 template <typename Dst, typename Src>
133 static constexpr auto limit_cast(Src value) noexcept
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)));
137 }
138 //------------------------------------------------------------------------------
143 template <typename Dst, typename Src>
144 static constexpr auto convert_if_fits(Src value) noexcept
145  -> std::enable_if_t<std::is_convertible_v<Src, Dst>, optionally_valid<Dst>> {
146 
147  if(is_within_limits<Dst>(value)) {
148  return {Dst(std::move(value)), true};
149  }
150  return {};
151 }
152 //------------------------------------------------------------------------------
153 } // namespace eagine
154 
155 EAGINE_DIAG_POP()
156 
157 #endif // EAGINE_IS_WITHIN_LIMITS_HPP
Common code is placed in this namespace.
Definition: eagine.hpp:21
Primary template for conditionally valid values.
Definition: decl.hpp:49
static constexpr auto convert_if_fits(Src value) noexcept -> std::enable_if_t< std::is_convertible_v< Src, Dst >, optionally_valid< Dst >>
Optionally converts value to Dst type if the value fits in that type.
Definition: is_within_limits.hpp:144
static constexpr auto limit_cast(Src value) noexcept -> std::enable_if_t< std::is_convertible_v< Src, Dst >, Dst >
Casts value to Dst type if the value fits in that type.
Definition: is_within_limits.hpp:133
std::integral_constant< bool, B > bool_constant
Alias for boolean constant type.
Definition: int_constant.hpp:20
static constexpr auto is_within_limits(Src value) noexcept
Indicates if value fits into the specified Dst type.
Definition: is_within_limits.hpp:122
math::sign< float > sign
Alias for math::sign.
Definition: sign.hpp:17

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).