convert_impl.hpp
Go to the documentation of this file.
1 #ifndef CONVERT_IMPL_HPP
2 #define CONVERT_IMPL_HPP
3 
4 #include <type_traits>
5 #include <exception>
6 #include "simple_string.hpp"
7 
8 namespace SafeAny
9 {
10 namespace details
11 {
12 template <typename BoolCondition>
13 using EnableIf = typename std::enable_if<BoolCondition::value, void>::type;
14 
15 template <typename T>
16 struct is_integer
17  : std::integral_constant<bool, std::is_integral<T>::value && !std::is_same<T, bool>::value &&
18  !std::is_same<T, char>::value>
19 {
20 };
21 
22 template <typename From, typename To>
24  : std::integral_constant<bool, std::is_same<From, To>::value && std::is_floating_point<To>::value>
25 {
26 };
27 
28 template <typename From, typename To>
30  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
31  sizeof(From) < sizeof(To) &&
32  std::is_signed<From>::value == std::is_signed<To>::value>
33 {
34 };
35 
36 template <typename T>
37 struct is_convertible_type
38  : std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value ||
39  std::is_same<T, bool>::value || std::is_same<T, char>::value ||
40  std::is_same<T, std::string>::value ||
41  std::is_same<T, SimpleString>::value || std::is_enum<T>::value>
42 {
43 };
44 
45 template <typename From, typename To>
46 struct float_conversion : std::integral_constant<bool, std::is_floating_point<From>::value &&
47  std::is_floating_point<To>::value &&
48  !std::is_same<From, To>::value>
49 {
50 };
51 
52 template <typename From, typename To>
53 struct unsigned_to_smaller_conversion
54  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
55  (sizeof(From) > sizeof(To)) && !std::is_signed<From>::value &&
56  !std::is_signed<To>::value>
57 {
58 };
59 
60 template <typename From, typename To>
61 struct signed_to_smaller_conversion
62  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
63  (sizeof(From) > sizeof(To)) && std::is_signed<From>::value &&
64  std::is_signed<To>::value>
65 {
66 };
67 
68 //---------------------------
69 template <typename From, typename To>
70 struct signed_to_smaller_unsigned_conversion
71  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
72  sizeof(From) >= sizeof(To) && std::is_signed<From>::value &&
73  !std::is_signed<To>::value>
74 {
75 };
76 
77 template <typename From, typename To>
78 struct signed_to_larger_unsigned_conversion
79  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
80  sizeof(From) < sizeof(To) && std::is_signed<From>::value &&
81  !std::is_signed<To>::value>
82 {
83 };
84 
85 template <typename From, typename To>
86 struct unsigned_to_smaller_signed_conversion
87  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
88  (sizeof(From) >= sizeof(To)) && !std::is_signed<From>::value &&
89  std::is_signed<To>::value>
90 {
91 };
92 
93 template <typename From, typename To>
94 struct unsigned_to_larger_signed_conversion
95  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
96  sizeof(From) < sizeof(To) && !std::is_signed<From>::value &&
97  std::is_signed<To>::value>
98 {
99 };
100 
101 template <typename From, typename To>
102 struct floating_to_signed_conversion
103  : std::integral_constant<bool, std::is_floating_point<From>::value && is_integer<To>::value &&
104  std::is_signed<To>::value>
105 {
106 };
107 
108 template <typename From, typename To>
109 struct floating_to_unsigned_conversion
110  : std::integral_constant<bool, std::is_floating_point<From>::value && is_integer<To>::value &&
111  !std::is_signed<To>::value>
112 {
113 };
114 
115 template <typename From, typename To>
116 struct integer_to_floating_conversion
117  : std::integral_constant<bool, is_integer<From>::value && std::is_floating_point<To>::value>
118 {
119 };
120 
121 template <typename From, typename To>
122 inline void checkUpperLimit(const From& from)
123 {
124  if ((sizeof(To) < sizeof(From)) && (from > static_cast<From>(std::numeric_limits<To>::max())))
125  {
126  throw std::runtime_error("Value too large.");
127  }
128  else if (static_cast<To>(from) > std::numeric_limits<To>::max())
129  {
130  throw std::runtime_error("Value too large.");
131  }
132 }
133 
134 template <typename From, typename To>
135 inline void checkUpperLimitFloat(const From& from)
136 {
137  if (from > std::numeric_limits<To>::max())
138  {
139  throw std::runtime_error("Value too large.");
140  }
141 }
142 
143 template <typename From, typename To>
144 inline void checkLowerLimitFloat(const From& from)
145 {
146  if ( from < -std::numeric_limits<To>::max())
147  {
148  throw std::runtime_error("Value too small.");
149  }
150 }
151 
152 template <typename From, typename To>
153 inline void checkLowerLimit(const From& from)
154 {
155  if (from < std::numeric_limits<To>::min())
156  {
157  throw std::runtime_error("Value too small.");
158  }
159 }
160 
161 template <typename From, typename To>
162 inline void checkTruncation(const From& from)
163 {
164  if (from != static_cast<From>(static_cast<To>(from)))
165  {
166  throw std::runtime_error("Floating point truncated");
167  }
168 }
169 
170 //----------------------- Implementation ----------------------------------------------
171 
172 template <typename SRC, typename DST>
173 inline typename std::enable_if<!is_convertible_type<DST>::value, void>::type
174 convertNumber(const SRC&, DST&)
175 {
176  static_assert(is_convertible_type<DST>::value, "Not convertible");
177 }
178 
179 template <typename SRC, typename DST>
180 inline EnableIf<std::is_same<bool, DST>> convertNumber(const SRC& from, DST& target)
181 {
182  target = (from != 0);
183 }
184 
185 template <typename SRC, typename DST>
186 inline EnableIf<std::is_same<SRC, DST>> convertNumber(const SRC& from, DST& target)
187 {
188  target = from;
189 }
190 
191 template <typename SRC, typename DST>
192 inline EnableIf<is_safe_integer_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
193 {
194  target = static_cast<DST>(from);
195 }
196 
197 template <typename SRC, typename DST>
198 inline EnableIf<float_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
199 {
200  checkTruncation<SRC, DST>(from);
201  target = static_cast<DST>(from);
202 }
203 
204 template <typename SRC, typename DST>
205 inline EnableIf<unsigned_to_smaller_conversion<SRC, DST>> convertNumber(const SRC& from,
206  DST& target)
207 {
208  checkUpperLimit<SRC, DST>(from);
209  target = static_cast<DST>(from);
210 }
211 
212 template <typename SRC, typename DST>
213 inline EnableIf<signed_to_smaller_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
214 {
215  checkLowerLimit<SRC, DST>(from);
216  checkUpperLimit<SRC, DST>(from);
217  target = static_cast<DST>(from);
218 }
219 
220 template <typename SRC, typename DST>
221 inline EnableIf<signed_to_smaller_unsigned_conversion<SRC, DST>> convertNumber(const SRC& from,
222  DST& target)
223 {
224  if (from < 0)
225  {
226  throw std::runtime_error("Value is negative and can't be converted to signed");
227  }
228 
229  checkUpperLimit<SRC, DST>(from);
230  target = static_cast<DST>(from);
231 }
232 
233 template <typename SRC, typename DST>
234 inline EnableIf<signed_to_larger_unsigned_conversion<SRC, DST>> convertNumber(const SRC& from,
235  DST& target)
236 {
237  if (from < 0)
238  {
239  throw std::runtime_error("Value is negative and can't be converted to signed");
240  }
241 
242  target = static_cast<DST>(from);
243 }
244 
245 template <typename SRC, typename DST>
246 inline EnableIf<unsigned_to_larger_signed_conversion<SRC, DST>> convertNumber(const SRC& from,
247  DST& target)
248 {
249  target = static_cast<DST>(from);
250 }
251 
252 template <typename SRC, typename DST>
253 inline EnableIf<unsigned_to_smaller_signed_conversion<SRC, DST>> convertNumber(const SRC& from,
254  DST& target)
255 {
256  checkUpperLimit<SRC, DST>(from);
257  target = static_cast<DST>(from);
258 }
259 
260 template <typename SRC, typename DST>
261 inline EnableIf<floating_to_signed_conversion<SRC, DST>> convertNumber(const SRC& from, DST& target)
262 {
263  checkLowerLimitFloat<SRC, DST>(from);
264  checkLowerLimitFloat<SRC, DST>(from);
265 
266  if (from != static_cast<SRC>(static_cast<DST>(from)))
267  {
268  throw std::runtime_error("Floating point truncated");
269  }
270 
271  target = static_cast<DST>(from);
272 }
273 
274 template <typename SRC, typename DST>
275 inline EnableIf<floating_to_unsigned_conversion<SRC, DST>> convertNumber(const SRC& from,
276  DST& target)
277 {
278  if (from < 0)
279  {
280  throw std::runtime_error("Value is negative and can't be converted to signed");
281  }
282 
283  if (from != static_cast<SRC>(static_cast<DST>(from)))
284  {
285  throw std::runtime_error("Floating point truncated");
286  }
287 
288  target = static_cast<DST>(from);
289 }
290 
291 template <typename SRC, typename DST>
292 inline EnableIf<integer_to_floating_conversion<SRC, DST>> convertNumber(const SRC& from,
293  DST& target)
294 {
295  checkTruncation<SRC, DST>(from);
296  target = static_cast<DST>(from);
297 }
298 
299 } //end namespace details
300 } //end namespace details
301 
302 #endif // CONVERT_IMPL_HPP
typename std::enable_if< BoolCondition::value, void >::type EnableIf


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:24