7 #ifndef CPPWAMP_INTERNAL_VARIANT_VISITORS_HPP
8 #define CPPWAMP_INTERNAL_VARIANT_VISITORS_HPP
10 #include "../blob.hpp"
11 #include "../error.hpp"
12 #include "../null.hpp"
13 #include "../traits.hpp"
14 #include "../variantdefs.hpp"
15 #include "../visitor.hpp"
16 #include "varianttraits.hpp"
28 using EnableIfBoolRef = EnableIf<isBool<T>() && !isSameType<T, bool>()>;
30 template <
typename T,
typename U>
31 constexpr
bool bothAreNumbers() {
return isNumber<T>() && isNumber<U>();}
33 template <
typename T,
typename U>
34 using EnableIfBothAreNumbers = EnableIf<bothAreNumbers<T, U>()>;
36 template <
typename T,
typename U>
37 using DisableIfBothAreNumbers = DisableIf<bothAreNumbers<T, U>()>;
40 using DisableIfVariant = DisableIf<isSameType<T, Variant>()>;
42 template <
typename TFrom,
typename TTo>
43 using EnableIfConvertible = EnableIf<std::is_convertible<TFrom,TTo>::value>;
45 template <
typename TFrom,
typename TTo>
46 using DisableIfConvertible = DisableIf<std::is_convertible<TFrom,TTo>::value>;
50 template <
typename TVariant>
51 class VariantEquivalentTo :
public Visitor<bool>
57 template <
typename TField>
58 bool operator()(
const TField& lhs,
const TField& rhs)
const
63 template <
typename TArg, EnableIfBoolRef<TArg> = 0>
64 bool operator()(
const bool lhs,
const TArg rhs)
const
66 return lhs == bool(rhs);
69 template <
typename TField,
typename TArg,
70 DisableIfBothAreNumbers<TField,TArg> = 0>
71 bool operator()(
const TField&,
const TArg&)
const {
return false;}
73 template <
typename TField,
typename TArg,
74 EnableIfBothAreNumbers<TField,TArg> = 0>
75 bool operator()(
const TField lhs,
const TArg rhs)
const
78 using LhsIsSigned =
typename std::is_signed<TField>;
79 using RhsIsSigned =
typename std::is_signed<TArg>;
80 return compareNumbers(LhsIsSigned(), RhsIsSigned(), lhs, rhs);
83 template <
typename TElem, DisableIfVariant<TElem> = 0>
84 bool operator()(
const ArrayType& lhs,
const std::vector<TElem>& rhs)
const
86 using VecConstRef =
typename std::vector<TElem>::const_reference;
90 return (lhs.size() != rhs.size()) ? false :
91 std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(),
92 [](
const Variant& lElem, VecConstRef rElem)
93 {return lElem == rElem;});
96 template <
typename TValue, DisableIfVariant<TValue> = 0>
97 bool operator()(
const ObjectType& lhs,
98 const std::map<String, TValue>& rhs)
const
100 using Map = std::map<String, TValue>;
101 using MapPair =
typename Map::value_type;
102 using ObjectPair =
typename ObjectType::value_type;
103 return (lhs.size() != rhs.size()) ? false :
104 std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(),
105 [](
const ObjectPair& lPair,
const MapPair& rPair)
107 return lPair.first == rPair.first &&
108 lPair.second == rPair.second;
113 template <
typename TField,
typename TArg>
115 const TField lhs,
const TArg rhs)
120 template <
typename TField,
typename TArg>
122 const TField lhs,
const TArg rhs)
126 using CT =
typename std::common_type<TField, TArg>::type;
127 return static_cast<CT
>(lhs) ==
static_cast<CT
>(rhs);
130 template <
typename TField,
typename TArg>
132 const TField lhs,
const TArg rhs)
136 using CT =
typename std::common_type<TField, TArg>::type;
137 return static_cast<CT
>(lhs) ==
static_cast<CT
>(rhs);
140 template <
typename TField,
typename TArg>
142 const TField lhs,
const TArg rhs)
149 template <
typename TVariant>
150 class VariantNotEquivalentTo :
public Visitor<bool>
156 template <
typename TField>
157 bool operator()(
const TField& lhs,
const TField& rhs)
const
160 template <
typename TArg, EnableIfBoolRef<TArg> = 0>
161 bool operator()(
const bool lhs,
const TArg rhs)
const
164 template <
typename TField,
typename TArg,
165 DisableIfBothAreNumbers<TField,TArg> = 0>
166 bool operator()(
const TField&,
const TArg&)
const {
return true;}
168 template <
typename TField,
typename TArg,
169 EnableIfBothAreNumbers<TField,TArg> = 0>
170 bool operator()(TField lhs, TArg rhs)
const
173 using LhsIsSigned =
typename std::is_signed<TField>;
174 using RhsIsSigned =
typename std::is_signed<TArg>;
175 return compareNumbers(LhsIsSigned(), RhsIsSigned(), lhs, rhs);
178 template <
typename TElem, DisableIfVariant<TElem> = 0>
179 bool operator()(
const ArrayType& lhs,
const std::vector<TElem>& rhs)
const
181 using VecConstRef =
typename std::vector<TElem>::const_reference;
185 return (lhs.size() != rhs.size()) ? true :
186 std::mismatch(lhs.cbegin(), lhs.cend(), rhs.cbegin(),
187 [](
const Variant& lElem, VecConstRef rElem)
188 {return lElem == rElem;}).first != lhs.cend();
191 template <
typename TValue, DisableIfVariant<TValue> = 0>
192 bool operator()(
const ObjectType& lhs,
193 const std::map<String, TValue>& rhs)
const
195 using Map = std::map<String, TValue>;
196 using MapPair =
typename Map::value_type;
197 using ObjectPair =
typename ObjectType::value_type;
199 auto comp = [](
const ObjectPair& lPair,
const MapPair& rPair)
201 return lPair.first == rPair.first &&
202 lPair.second == rPair.second;
205 return (lhs.size() != rhs.size()) ?
true :
206 ( std::mismatch(lhs.cbegin(), lhs.cend(), rhs.cbegin(),
207 std::move(comp)).first != lhs.end() );
211 template <
typename TField,
typename TArg>
213 const TField lhs,
const TArg rhs)
218 template <
typename TField,
typename TArg>
220 const TField lhs,
const TArg rhs)
224 using CT =
typename std::common_type<TField, TArg>::type;
225 return static_cast<CT
>(lhs) !=
static_cast<CT
>(rhs);
228 template <
typename TField,
typename TArg>
230 const TField lhs,
const TArg rhs)
234 using CT =
typename std::common_type<TField, TArg>::type;
235 return static_cast<CT
>(lhs) !=
static_cast<CT
>(rhs);
238 template <
typename TField,
typename TArg>
240 const TField lhs,
const TArg rhs)
248 template <
typename TVariant>
249 class VariantIsConvertibleTo :
public Visitor<bool>
255 template <
typename T>
struct Tag {};
258 template <
typename TField>
259 bool operator()(
const TField&, Tag<TField>)
const {
return true;}
262 template <
typename TField,
typename TResult,
263 internal::EnableIfConvertible<TField,TResult> = 0>
264 bool operator()(
const TField&, Tag<TResult>)
const {
return true;}
267 template <
typename TField,
typename TResult,
268 internal::DisableIfConvertible<TField,TResult> = 0>
269 bool operator()(
const TField&, Tag<TResult>)
const {
return false;}
272 template <
typename TElem,
internal::DisableIfVariant<TElem> = 0>
273 bool operator()(
const ArrayType& from, Tag<std::vector<TElem>>)
const
278 for (
const auto& fromElem: from)
280 if (!applyWithOperand(*
this, fromElem, toElem))
287 template <
typename TValue,
internal::DisableIfVariant<TValue> = 0>
288 bool operator()(
const ObjectType& from, Tag<std::map<String, TValue>>)
const
293 for (
const auto& fromKv: from)
295 if (!applyWithOperand(*
this, fromKv.second, toValue))
303 template <
typename TVariant>
304 class VariantConvertTo :
public Visitor<>
311 template <
typename TField>
312 void operator()(
const TField& from, TField& to)
const {to = from;}
315 template <
typename TField,
typename TResult,
316 internal::EnableIfConvertible<TField,TResult> = 0>
317 void operator()(
const TField& from, TResult& to)
const
319 to =
static_cast<TResult
>(from);
323 template <
typename TField,
typename TResult,
324 internal::DisableIfConvertible<TField,TResult> = 0>
325 void operator()(
const TField&, TResult&)
const
327 throw error::Conversion(
328 "wamp::error::Conversion: Invalid conversion "
329 "from " + FieldTraits<TField>::typeName() +
330 " to " + ArgTraits<TResult>::typeName());
334 template <
typename TElem,
internal::DisableIfVariant<TElem> = 0>
335 void operator()(
const ArrayType& from, std::vector<TElem>& to)
const
338 for (
size_t i=0; i<from.size(); ++i)
342 applyWithOperand(*
this, from.at(i), toElem);
344 catch (
const error::Conversion& e)
346 std::ostringstream oss;
347 oss << e.what() <<
" (for Array element #" << i <<
')';
348 throw error::Conversion(oss.str());
350 to.push_back(std::move(toElem));
355 template <
typename TValue,
internal::DisableIfVariant<TValue> = 0>
356 void operator()(
const ObjectType& from, std::map<String, TValue>& to)
const
359 for (
const auto& fromKv: from)
363 applyWithOperand(*
this, fromKv.second, toValue);
365 catch (
const error::Conversion& e)
367 std::ostringstream oss;
368 oss << e.what() <<
" (for Object member \""
369 << fromKv.first <<
"\")";
370 throw error::Conversion(oss.str());
372 to.emplace(fromKv.first, std::move(toValue));
378 class VariantTypeName :
public Visitor<String>
381 template <
typename TField>
String operator()(
const TField&)
const
383 return FieldTraits<TField>::typeName();
391 #endif // CPPWAMP_INTERNAL_VARIANT_VISITORS_HPP