2
3
4
5
6
7
8
9
10
11
29template <
typename BoolCondition>
30using EnableIf =
typename std::enable_if<BoolCondition::value,
void>::type;
33constexpr bool is_integer()
35 return std::is_same<T,
bool>::value || std::is_same<T,
char>::value ||
36 std::is_integral<T>::value;
40constexpr bool is_convertible_type()
42 return is_integer<T>() || std::is_floating_point<T>::value ||
43 std::is_same<T, std::string>::value || std::is_same<T,
SimpleString>::value ||
44 std::is_enum<T>::value;
48constexpr bool is_convertible_to_bool()
50 return is_integer<T>() || std::is_floating_point<T>::value || std::is_enum<T>::value;
54constexpr bool is_signed()
56 return std::is_signed<T>::value;
59template <
typename T1,
typename T2>
60constexpr bool is_same()
62 return std::is_same<T1, T2>::value;
65template <
typename From,
typename To>
66inline void checkUpperLimit(
const From& from)
68 if(from >
static_cast<From>(std::numeric_limits<To>::max()))
70 throw std::runtime_error(
"Value outside the max numerical limit.");
74template <
typename From,
typename To>
75inline void checkLowerLimit(
const From& from)
77 if constexpr(std::is_same<To,
bool>::value)
79 if(from != 0 && from != 1)
81 throw std::runtime_error(
"Implicit casting to bool is not allowed");
84 else if(from < std::numeric_limits<To>::min())
86 throw std::runtime_error(
"Value outside the lovest numerical limit.");
90template <
typename From,
typename To>
91inline void checkTruncation(
const From& from)
94 if constexpr(std::is_integral_v<From> && std::is_floating_point_v<To>)
97 constexpr uint64_t max_exact = (1LL << std::numeric_limits<
double>::digits) - 1;
98 bool doesnt_fit =
false;
99 if constexpr(!std::is_signed_v<From>)
101 doesnt_fit =
static_cast<uint64_t>(from) > max_exact;
105 doesnt_fit = std::abs(
static_cast<int64_t>(from)) >
static_cast<int64_t>(max_exact);
109 throw std::runtime_error(
"Loss of precision when converting a large integer number "
110 "to floating point:" +
111 std::to_string(from));
115 else if constexpr(std::is_floating_point_v<From> && std::is_integral_v<To>)
117 if(from >
static_cast<From>(std::numeric_limits<To>::max()) ||
118 from <
static_cast<From>(std::numeric_limits<To>::lowest()) ||
119 from != std::nearbyint(from))
121 throw std::runtime_error(
"Invalid floating point to integer conversion");
127 if(from >
static_cast<From>(std::numeric_limits<To>::max()) ||
128 from <
static_cast<From>(std::numeric_limits<To>::lowest()))
130 throw std::runtime_error(
"Value outside numeric limits");
132 To as_target =
static_cast<To>(from);
133 From back_to_source =
static_cast<From>(as_target);
134 if(from != back_to_source)
136 throw std::runtime_error(
"Value truncated in conversion");
143template <
typename SRC,
typename DST>
144void convertNumber(
const SRC& source, DST& target)
146 static_assert(is_convertible_type<SRC>() && is_convertible_type<DST>(),
"Not "
149 constexpr bool both_integers = is_integer<SRC>() && is_integer<DST>();
151 if constexpr(is_signed<SRC>() && !is_signed<DST>())
155 throw std::runtime_error(
"Value is negative and can't be converted to unsigned");
162 if constexpr(is_same<SRC, DST>() || (is_same<SRC,
float>() && is_same<DST,
double>()) ||
163 (std::is_floating_point<SRC>::value && is_same<DST,
bool>()))
165 target =
static_cast<DST>(source);
168 else if constexpr(is_integer<SRC>() && is_same<DST,
bool>())
170 checkLowerLimit<SRC, DST>(source);
171 target =
static_cast<DST>(source);
173 else if constexpr(both_integers)
175 if constexpr(
sizeof(SRC) ==
sizeof(DST) && !is_signed<SRC>() && is_signed<DST>())
177 checkUpperLimit<SRC, DST>(source);
180 else if constexpr(
sizeof(SRC) >
sizeof(DST))
182 if constexpr(is_signed<SRC>())
184 checkLowerLimit<SRC, DST>(source);
186 checkUpperLimit<SRC, DST>(source);
188 target =
static_cast<DST>(source);
191 else if constexpr(std::is_floating_point<SRC>::value ||
192 std::is_floating_point<DST>::value)
195 std::is_floating_point<SRC>::value && std::is_floating_point<DST>::value;
199 checkTruncation<SRC, DST>(source);
201 target =
static_cast<DST>(source);
Definition: simple_string.hpp:19