35 #ifndef VARIANT_IMPL_H 36 #define VARIANT_IMPL_H 38 #include <type_traits> 53 template <
typename BoolCondition>
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>
63 template <
typename From,
typename To>
65 std::is_same<From, To>::value
66 && std::is_floating_point<To>::value >
70 template <
typename From,
typename To>
72 : std::integral_constant<bool, is_integer<From>::value
73 && is_integer<To>::value
74 && sizeof(From) <= sizeof(To)
75 && std::is_signed<From>::value == std::is_signed<To>::value>
78 template <typename From, typename To>
79 struct float_conversion
80 : std::integral_constant<bool, std::is_floating_point<From>::value
81 && std::is_floating_point<To>::value
82 && !std::is_same<From,To>::value >
85 template <typename From, typename To>
86 struct unsigned_to_smaller_conversion
87 : std::integral_constant<bool, is_integer<From>::value
88 && is_integer<To>::value
89 && (sizeof(From) > sizeof(To))
90 && !std::is_signed<From>::value
91 && !std::is_signed<To>::value >
94 template <
typename From,
typename To>
95 struct signed_to_smaller_conversion
96 : std::integral_constant<bool, is_integer<From>::value
97 && is_integer<To>::value
98 && (sizeof(From) > sizeof(To))
99 && std::is_signed<From>::value
100 && std::is_signed<To>::value >
104 template <
typename From,
typename To>
105 struct signed_to_smaller_unsigned_conversion
106 : std::integral_constant<bool, is_integer<From>::value
107 && is_integer<To>::value
108 && sizeof(From) >= sizeof(To)
109 && std::is_signed<From>::value
110 && !std::is_signed<To>::value >
113 template <
typename From,
typename To>
114 struct signed_to_larger_unsigned_conversion
115 : std::integral_constant<bool, is_integer<From>::value
116 && is_integer<To>::value
117 && sizeof(From) < sizeof(To)
118 && std::is_signed<From>::value
119 && !std::is_signed<To>::value >
122 template <typename From, typename To>
123 struct unsigned_to_smaller_signed_conversion
124 : std::integral_constant<bool, is_integer<From>::value
125 && is_integer<To>::value
126 && (sizeof(From) >= sizeof(To))
127 && !std::is_signed<From>::value
128 && std::is_signed<To>::value >
131 template <
typename From,
typename To>
132 struct unsigned_to_larger_signed_conversion
133 : std::integral_constant<bool, is_integer<From>::value
134 && is_integer<To>::value
135 && sizeof(From) < sizeof(To)
136 && !std::is_signed<From>::value
137 && std::is_signed<To>::value >
140 template <typename From, typename To>
141 struct floating_to_signed_conversion
142 : std::integral_constant<bool, std::is_floating_point<From>::value
143 && is_integer<To>::value
144 && std::is_signed<To>::value >
147 template <typename From, typename To>
148 struct floating_to_unsigned_conversion
149 : std::integral_constant<bool, std::is_floating_point<From>::value
150 && is_integer<To>::value
151 && !std::is_signed<To>::value >
154 template <typename From, typename To>
155 struct integer_to_floating_conversion
156 : std::integral_constant<bool, is_integer<From>::value
157 && std::is_floating_point<To>::value >
160 template <typename From, typename To>
161 inline void checkUpperLimit(const From& from)
163 if ((sizeof(To) < sizeof(From)) &&
164 (from > static_cast<From>(std::numeric_limits<To>::max()))) {
165 throw RangeException("Value too large.");
167 else if (static_cast<To>(from) > std::numeric_limits<To>::max()) {
172 template <
typename From,
typename To>
173 inline void checkUpperLimitFloat(
const From& from)
175 if (from > std::numeric_limits<To>::max()){
180 template <
typename From,
typename To>
181 inline void checkLowerLimitFloat(
const From& from)
183 if (from < -std::numeric_limits<To>::max()){
188 template <
typename From,
typename To>
189 inline void checkLowerLimit(
const From& from)
191 if (from < std::numeric_limits<To>::min()){
196 template <
typename From,
typename To>
197 inline void checkTruncation(
const From& from)
199 if( from != static_cast<From>(static_cast<To>( from))){
207 template<
typename SRC,
typename DST,
209 inline void convert_impl(
const SRC& from, DST& target )
215 template<
typename SRC,
typename DST,
217 inline void convert_impl(
const SRC& from, DST& target )
219 target =
static_cast<DST
>( from);
222 template<
typename SRC,
typename DST,
224 inline void convert_impl(
const SRC& from, DST& target )
226 if( std::isnan(from) ){
227 target = std::numeric_limits<DST>::quiet_NaN();
229 else if( std::isinf(from) ){
230 target = std::numeric_limits<DST>::infinity();
233 checkTruncation<SRC,DST>(from);
234 target =
static_cast<DST
>( from );
239 template<
typename SRC,
typename DST,
241 inline void convert_impl(
const SRC& from, DST& target )
245 checkUpperLimit<SRC,DST>(from);
246 target =
static_cast<DST
>( from);
249 template<
typename SRC,
typename DST,
251 inline void convert_impl(
const SRC& from, DST& target )
254 checkLowerLimit<SRC,DST>(from);
255 checkUpperLimit<SRC,DST>(from);
256 target =
static_cast<DST
>( from);
260 template<
typename SRC,
typename DST,
262 inline void convert_impl(
const SRC& from, DST& target )
266 throw RangeException(
"Value is negative and can't be converted to signed");
268 checkUpperLimit<SRC,DST>(from);
270 target =
static_cast<DST
>( from);
274 template<
typename SRC,
typename DST,
276 inline void convert_impl(
const SRC& from, DST& target )
281 throw RangeException(
"Value is negative and can't be converted to signed");
283 target =
static_cast<DST
>( from);
286 template<
typename SRC,
typename DST,
288 inline void convert_impl(
const SRC& from, DST& target )
291 target =
static_cast<DST
>( from);
294 template<
typename SRC,
typename DST,
296 inline void convert_impl(
const SRC& from, DST& target )
298 checkUpperLimit<SRC,DST>(from);
299 target =
static_cast<DST
>( from);
302 template<
typename SRC,
typename DST,
304 inline void convert_impl(
const SRC& from, DST& target )
306 checkLowerLimitFloat<SRC,DST>(from);
307 checkLowerLimitFloat<SRC,DST>(from);
309 if( from != static_cast<SRC>(static_cast<DST>( from))){
313 target =
static_cast<DST
>( from);
316 template<
typename SRC,
typename DST,
318 inline void convert_impl(
const SRC& from, DST& target )
321 throw RangeException(
"Value is negative and can't be converted to signed");
324 checkLowerLimitFloat<SRC,DST>(from);
326 if( from != static_cast<SRC>(static_cast<DST>( from)))
329 target =
static_cast<DST
>( from);
332 template<
typename SRC,
typename DST,
334 inline void convert_impl(
const SRC& from, DST& target )
336 checkTruncation<SRC,DST>(from);
337 target =
static_cast<DST
>( from);
Invoke< std::enable_if< BoolCondition::value > > EnableIf