conversion_impl.hpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright 2016-2017 Davide Faconti
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  * *******************************************************************/
34 
35 #ifndef VARIANT_IMPL_H
36 #define VARIANT_IMPL_H
37 
38 #include <type_traits>
39 #include <limits>
40 #include <iostream>
41 #include <cmath>
44 
45 namespace RosMsgParser
46 {
47 
48 namespace details
49 {
50 
51 template <typename T>
52 using Invoke = typename T::type;
53 
54 template <typename BoolCondition>
55 using EnableIf = Invoke<std::enable_if<BoolCondition::value>>;
56 
57 template <typename T>
58 struct is_integer : std::integral_constant<bool, std::is_integral<T>::value &&
59  !std::is_same<T, bool>::value &&
60  !std::is_same<T, char>::value>
61 {
62 };
63 
64 template <typename From, typename To>
65 struct is_same_real : std::integral_constant<bool, std::is_same<From, To>::value &&
66  std::is_floating_point<To>::value>
67 {
68 };
69 
70 template <typename From, typename To>
71 struct is_safe_integer_conversion
72  : std::integral_constant<bool,
73  is_integer<From>::value && is_integer<To>::value &&
74  sizeof(From) <= sizeof(To) &&
75  std::is_signed<From>::value == std::is_signed<To>::value>
76 {
77 };
78 
79 template <typename From, typename To>
80 struct float_conversion
81  : std::integral_constant<bool, std::is_floating_point<From>::value &&
82  std::is_floating_point<To>::value &&
83  !std::is_same<From, To>::value>
84 {
85 };
86 
87 template <typename From, typename To>
88 struct unsigned_to_smaller_conversion
89  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
90  (sizeof(From) > sizeof(To)) &&
91  !std::is_signed<From>::value &&
92  !std::is_signed<To>::value>
93 {
94 };
95 
96 template <typename From, typename To>
97 struct signed_to_smaller_conversion
98  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
99  (sizeof(From) > sizeof(To)) &&
100  std::is_signed<From>::value &&
101  std::is_signed<To>::value>
102 {
103 };
104 
105 //---------------------------
106 template <typename From, typename To>
107 struct signed_to_smaller_unsigned_conversion
108  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
109  sizeof(From) >= sizeof(To) &&
110  std::is_signed<From>::value &&
111  !std::is_signed<To>::value>
112 {
113 };
114 
115 template <typename From, typename To>
116 struct signed_to_larger_unsigned_conversion
117  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
118  sizeof(From) < sizeof(To) &&
119  std::is_signed<From>::value &&
120  !std::is_signed<To>::value>
121 {
122 };
123 
124 template <typename From, typename To>
125 struct unsigned_to_smaller_signed_conversion
126  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
127  (sizeof(From) >= sizeof(To)) &&
128  !std::is_signed<From>::value &&
129  std::is_signed<To>::value>
130 {
131 };
132 
133 template <typename From, typename To>
134 struct unsigned_to_larger_signed_conversion
135  : std::integral_constant<bool, is_integer<From>::value && is_integer<To>::value &&
136  sizeof(From) < sizeof(To) &&
137  !std::is_signed<From>::value &&
138  std::is_signed<To>::value>
139 {
140 };
141 
142 template <typename From, typename To>
143 struct floating_to_signed_conversion
144  : std::integral_constant<bool, std::is_floating_point<From>::value &&
145  is_integer<To>::value && std::is_signed<To>::value>
146 {
147 };
148 
149 template <typename From, typename To>
150 struct floating_to_unsigned_conversion
151  : std::integral_constant<bool, std::is_floating_point<From>::value &&
152  is_integer<To>::value && !std::is_signed<To>::value>
153 {
154 };
155 
156 template <typename From, typename To>
157 struct integer_to_floating_conversion
158  : std::integral_constant<bool,
159  is_integer<From>::value && std::is_floating_point<To>::value>
160 {
161 };
162 
163 template <typename From, typename To>
164 inline void checkUpperLimit(const From& from)
165 {
166  if ((sizeof(To) < sizeof(From)) &&
167  (from > static_cast<From>(std::numeric_limits<To>::max())))
168  {
169  throw RangeException("Value too large.");
170  }
171  else if (static_cast<To>(from) > std::numeric_limits<To>::max())
172  {
173  throw RangeException("Value too large.");
174  }
175 }
176 
177 template <typename From, typename To>
178 inline void checkUpperLimitFloat(const From& from)
179 {
180  if (from > std::numeric_limits<To>::max())
181  {
182  throw RangeException("Value too large.");
183  }
184 }
185 
186 template <typename From, typename To>
187 inline void checkLowerLimitFloat(const From& from)
188 {
189  if (from < -std::numeric_limits<To>::max())
190  {
191  throw RangeException("Value too small.");
192  }
193 }
194 
195 template <typename From, typename To>
196 inline void checkLowerLimit(const From& from)
197 {
198  if (from < std::numeric_limits<To>::min())
199  {
200  throw RangeException("Value too small.");
201  }
202 }
203 
204 template <typename From, typename To>
205 inline void checkTruncation(const From& from)
206 {
207  if (from != static_cast<From>(static_cast<To>(from)))
208  {
209  throw RangeException("Floating point truncated");
210  }
211 }
212 
213 //----------------------- Implementation ----------------------------------------------
214 
215 template <typename SRC, typename DST,
216  typename details::EnableIf<details::is_same_real<SRC, DST>>* = nullptr>
217 inline void convert_impl(const SRC& from, DST& target)
218 {
219  target = from;
220 }
221 
222 template <
223  typename SRC, typename DST,
224  typename details::EnableIf<details::is_safe_integer_conversion<SRC, DST>>* = nullptr>
225 inline void convert_impl(const SRC& from, DST& target)
226 {
227  target = static_cast<DST>(from);
228 }
229 
230 template <typename SRC, typename DST,
231  typename details::EnableIf<details::float_conversion<SRC, DST>>* = nullptr>
232 inline void convert_impl(const SRC& from, DST& target)
233 {
234  if (!std::isnan(from))
235  {
236  checkTruncation<SRC, DST>(from);
237  }
238  target = static_cast<DST>(from);
239 }
240 
241 template <typename SRC, typename DST,
242  typename details::EnableIf<details::unsigned_to_smaller_conversion<SRC, DST>>* =
243  nullptr>
244 inline void convert_impl(const SRC& from, DST& target)
245 {
246  checkUpperLimit<SRC, DST>(from);
247  target = static_cast<DST>(from);
248 }
249 
250 template <typename SRC, typename DST,
251  typename details::EnableIf<details::signed_to_smaller_conversion<SRC, DST>>* =
252  nullptr>
253 inline void convert_impl(const SRC& from, DST& target)
254 {
255  checkLowerLimit<SRC, DST>(from);
256  checkUpperLimit<SRC, DST>(from);
257  target = static_cast<DST>(from);
258 }
259 
260 template <typename SRC, typename DST,
261  typename details::EnableIf<
262  details::signed_to_smaller_unsigned_conversion<SRC, DST>>* = nullptr>
263 inline void convert_impl(const SRC& from, DST& target)
264 {
265  if (from < 0)
266  {
267  throw RangeException("Value is negative and can't be converted to signed");
268  }
269 
270  checkUpperLimit<SRC, DST>(from);
271  target = static_cast<DST>(from);
272 }
273 
274 template <typename SRC, typename DST,
275  typename details::EnableIf<
276  details::signed_to_larger_unsigned_conversion<SRC, DST>>* = nullptr>
277 inline void convert_impl(const SRC& from, DST& target)
278 {
279  if (from < 0)
280  {
281  throw RangeException("Value is negative and can't be converted to signed");
282  }
283 
284  target = static_cast<DST>(from);
285 }
286 
287 template <typename SRC, typename DST,
288  typename details::EnableIf<
289  details::unsigned_to_larger_signed_conversion<SRC, DST>>* = nullptr>
290 inline void convert_impl(const SRC& from, DST& target)
291 {
292  target = static_cast<DST>(from);
293 }
294 
295 template <typename SRC, typename DST,
296  typename details::EnableIf<
297  details::unsigned_to_smaller_signed_conversion<SRC, DST>>* = nullptr>
298 inline void convert_impl(const SRC& from, DST& target)
299 {
300  checkUpperLimit<SRC, DST>(from);
301  target = static_cast<DST>(from);
302 }
303 
304 template <typename SRC, typename DST,
305  typename details::EnableIf<details::floating_to_signed_conversion<SRC, DST>>* =
306  nullptr>
307 inline void convert_impl(const SRC& from, DST& target)
308 {
309  checkLowerLimitFloat<SRC, DST>(from);
310  checkUpperLimitFloat<SRC, DST>(from);
311 
312  if (from != static_cast<SRC>(static_cast<DST>(from)))
313  {
314  throw RangeException("Floating point truncated");
315  }
316 
317  target = static_cast<DST>(from);
318 }
319 
320 template <typename SRC, typename DST,
321  typename details::EnableIf<
322  details::floating_to_unsigned_conversion<SRC, DST>>* = nullptr>
323 inline void convert_impl(const SRC& from, DST& target)
324 {
325  if (from < 0)
326  {
327  throw RangeException("Value is negative and can't be converted to signed");
328  }
329 
330  checkLowerLimitFloat<SRC, DST>(from);
331 
332  if (from != static_cast<SRC>(static_cast<DST>(from)))
333  {
334  throw RangeException("Floating point truncated");
335  }
336 
337  target = static_cast<DST>(from);
338 }
339 
340 template <typename SRC, typename DST,
341  typename details::EnableIf<details::integer_to_floating_conversion<SRC, DST>>* =
342  nullptr>
343 inline void convert_impl(const SRC& from, DST& target)
344 {
345  checkTruncation<SRC, DST>(from);
346  target = static_cast<DST>(from);
347 }
348 
349 } // end namespace details
350 
351 } // namespace RosMsgParser
352 
353 #endif // VARIANT_H
exceptions.hpp
backward::ColorMode::type
type
Definition: backward.hpp:3600
detail::is_integer
bool_constant< is_integral< T >::value &&!std::is_same< T, bool >::value &&!std::is_same< T, char >::value &&!std::is_same< T, wchar_t >::value > is_integer
Definition: format.h:782
RosMsgParser::details::EnableIf
Invoke< std::enable_if< BoolCondition::value > > EnableIf
Definition: conversion_impl.hpp:119
RosMsgParser
Definition: builtin_types.hpp:34
builtin_types.hpp
RosMsgParser::RangeException
Definition: exceptions.hpp:76
detail::is_signed
std::integral_constant< bool, std::numeric_limits< T >::is_signed||std::is_same< T, int128_opt >::value > is_signed
Definition: format.h:776
RosMsgParser::details::Invoke
typename T::type Invoke
Definition: conversion_impl.hpp:116
detail::isnan
constexpr auto isnan(T value) -> bool
Definition: format.h:2734


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:43