1 #ifndef CONVERT_IMPL_HPP
2 #define CONVERT_IMPL_HPP
12 template <
typename BoolCondition>
13 using EnableIf =
typename std::enable_if<BoolCondition::value, void>::type;
17 : std::integral_constant<bool, std::is_integral<T>::value && !std::is_same<T, bool>::value &&
18 !std::is_same<T, char>::value>
22 template <
typename From,
typename To>
24 : std::integral_constant<bool, std::is_same<From, To>::value && std::is_floating_point<To>::value>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
121 template <typename From, typename To>
122 inline void checkUpperLimit(const From& from)
124 if ((sizeof(To) < sizeof(From)) && (from > static_cast<From>(std::numeric_limits<To>::max())))
126 throw std::runtime_error("Value too large.");
128 else if (static_cast<To>(from) > std::numeric_limits<To>::max())
130 throw std::runtime_error(
"Value too large.");
134 template <
typename From,
typename To>
135 inline void checkUpperLimitFloat(
const From& from)
137 if (from > std::numeric_limits<To>::max())
139 throw std::runtime_error(
"Value too large.");
143 template <
typename From,
typename To>
144 inline void checkLowerLimitFloat(
const From& from)
146 if ( from < -std::numeric_limits<To>::max())
148 throw std::runtime_error(
"Value too small.");
152 template <
typename From,
typename To>
153 inline void checkLowerLimit(
const From& from)
155 if (from < std::numeric_limits<To>::min())
157 throw std::runtime_error(
"Value too small.");
161 template <
typename From,
typename To>
162 inline void checkTruncation(
const From& from)
164 if (from !=
static_cast<From
>(
static_cast<To
>(from)))
166 throw std::runtime_error(
"Floating point truncated");
172 template <
typename SRC,
typename DST>
173 inline typename std::enable_if<!is_convertible_type<DST>::value,
void>::type
174 convertNumber(
const SRC&, DST&)
176 static_assert(is_convertible_type<DST>::value,
"Not convertible");
179 template <
typename SRC,
typename DST>
180 inline EnableIf<std::is_same<bool, DST>> convertNumber(
const SRC& from, DST& target)
182 target = (from != 0);
185 template <
typename SRC,
typename DST>
186 inline EnableIf<std::is_same<SRC, DST>> convertNumber(
const SRC& from, DST& target)
191 template <
typename SRC,
typename DST>
192 inline EnableIf<is_safe_integer_conversion<SRC, DST>> convertNumber(
const SRC& from, DST& target)
194 target =
static_cast<DST
>(from);
197 template <
typename SRC,
typename DST>
198 inline EnableIf<float_conversion<SRC, DST>> convertNumber(
const SRC& from, DST& target)
200 checkTruncation<SRC, DST>(from);
201 target =
static_cast<DST
>(from);
204 template <
typename SRC,
typename DST>
205 inline EnableIf<unsigned_to_smaller_conversion<SRC, DST>> convertNumber(
const SRC& from,
208 checkUpperLimit<SRC, DST>(from);
209 target =
static_cast<DST
>(from);
212 template <
typename SRC,
typename DST>
213 inline EnableIf<signed_to_smaller_conversion<SRC, DST>> convertNumber(
const SRC& from, DST& target)
215 checkLowerLimit<SRC, DST>(from);
216 checkUpperLimit<SRC, DST>(from);
217 target =
static_cast<DST
>(from);
220 template <
typename SRC,
typename DST>
221 inline EnableIf<signed_to_smaller_unsigned_conversion<SRC, DST>> convertNumber(
const SRC& from,
226 throw std::runtime_error(
"Value is negative and can't be converted to signed");
229 checkUpperLimit<SRC, DST>(from);
230 target =
static_cast<DST
>(from);
233 template <
typename SRC,
typename DST>
234 inline EnableIf<signed_to_larger_unsigned_conversion<SRC, DST>> convertNumber(
const SRC& from,
239 throw std::runtime_error(
"Value is negative and can't be converted to signed");
242 target =
static_cast<DST
>(from);
245 template <
typename SRC,
typename DST>
246 inline EnableIf<unsigned_to_larger_signed_conversion<SRC, DST>> convertNumber(
const SRC& from,
249 target =
static_cast<DST
>(from);
252 template <
typename SRC,
typename DST>
253 inline EnableIf<unsigned_to_smaller_signed_conversion<SRC, DST>> convertNumber(
const SRC& from,
256 checkUpperLimit<SRC, DST>(from);
257 target =
static_cast<DST
>(from);
260 template <
typename SRC,
typename DST>
261 inline EnableIf<floating_to_signed_conversion<SRC, DST>> convertNumber(
const SRC& from, DST& target)
263 checkLowerLimitFloat<SRC, DST>(from);
264 checkLowerLimitFloat<SRC, DST>(from);
266 if (from !=
static_cast<SRC
>(
static_cast<DST
>(from)))
268 throw std::runtime_error(
"Floating point truncated");
271 target =
static_cast<DST
>(from);
274 template <
typename SRC,
typename DST>
275 inline EnableIf<floating_to_unsigned_conversion<SRC, DST>> convertNumber(
const SRC& from,
280 throw std::runtime_error(
"Value is negative and can't be converted to signed");
283 if (from !=
static_cast<SRC
>(
static_cast<DST
>(from)))
285 throw std::runtime_error(
"Floating point truncated");
288 target =
static_cast<DST
>(from);
291 template <
typename SRC,
typename DST>
292 inline EnableIf<integer_to_floating_conversion<SRC, DST>> convertNumber(
const SRC& from,
295 checkTruncation<SRC, DST>(from);
296 target =
static_cast<DST
>(from);
302 #endif // CONVERT_IMPL_HPP