7 #ifndef CPPWAMP_VARIANT_HPP
8 #define CPPWAMP_VARIANT_HPP
23 #include <type_traits>
34 #include "internal/varianttraits.hpp"
35 #include "internal/variantvisitors.hpp"
57 #define CPPWAMP_CONVERSION_SPLIT_FREE(Type) \
58 inline void convert(::wamp::FromVariantConverter& c, Type& obj) \
60 convertFrom(c, obj); \
63 inline void convert(::wamp::ToVariantConverter& c, Type& obj) \
65 convertTo(c, const_cast<const Type&>(obj)); \
88 #define CPPWAMP_CONVERSION_SPLIT_MEMBER(Type) \
89 inline void convert(::wamp::FromVariantConverter& c, Type& obj) \
91 wamp::ConversionAccess::convertFrom(c, obj); \
94 inline void convert(::wamp::ToVariantConverter& c, Type& obj) \
96 const auto& constObj = obj; \
97 wamp::ConversionAccess::convertTo(c, constObj); \
106 namespace internal {
template <TypeId typeId>
struct FieldTypeForId;}
137 template <
typename TField,
typename Enable =
void>
138 using ArgTraits = internal::ArgTraits<TField>;
144 template <TypeId typeId>
149 template <
typename T>
152 return ArgTraits<ValueTypeOf<T>>::isValid;
157 template <
typename T>
158 static constexpr
bool isInvalidArg() noexcept
160 return !ArgTraits<ValueTypeOf<T>>::isValid &&
161 !isSameType<T, Variant>();
165 template <
typename T>
166 static constexpr
bool isVariantArg() noexcept
168 return isSameType<ValueTypeOf<T>, Variant>();
196 template <
typename TValue>
197 static Variant from(TValue&& value);
209 template <typename T, CPPWAMP_ENABLE_IF(
Variant::isValidArg<T>()) = 0>
217 template <typename T>
Variant(std::vector<T> vec);
237 explicit operator
bool() const;
241 template <typename TBound>
bool is() const;
245 template <
TypeId id>
bool is() const;
248 template <typename T> T to() const;
252 template <typename T>
void to(T& value) const;
256 template <typename T>
268 template <typename TBound> TBound& as();
271 template <typename TBound> const TBound& as() const;
306 bool operator==(const
Variant& other) const;
309 bool operator!=(const
Variant& other) const;
312 bool operator<(const
Variant& other) const;
326 template <typename T>
Variant& operator=(T value);
332 template <typename T>
Variant& operator=(std::vector<T> vec);
338 template <typename T>
Variant& operator=(std::map<
String, T> map);
341 void swap(
Variant& other) noexcept;
346 class CPPWAMP_HIDDEN Construct;
347 class CPPWAMP_HIDDEN MoveConstruct;
348 class CPPWAMP_HIDDEN MoveAssign;
349 class CPPWAMP_HIDDEN Destruct;
350 class CPPWAMP_HIDDEN Swap;
351 class CPPWAMP_HIDDEN ElementCount;
352 class CPPWAMP_HIDDEN LessThan;
353 class CPPWAMP_HIDDEN Output;
355 template <typename TField>
356 using FieldTraits = internal::FieldTraits<TField>;
358 template <typename TField>
359 using Access = internal::Access<TField>;
361 template <typename... TFields> struct CPPWAMP_HIDDEN TypeMask;
363 template <
TypeId... typeIds> struct CPPWAMP_HIDDEN TypeIdMask;
365 template <typename TValue, typename TArg>
366 CPPWAMP_HIDDEN
void constructAs(TArg&& value);
368 template <typename TField>
369 CPPWAMP_HIDDEN
void destructAs();
375 CPPWAMP_HIDDEN static
Variant convertFrom(T&& value);
378 CPPWAMP_HIDDEN static
Variant convertFrom(const T& value);
381 CPPWAMP_HIDDEN static
Variant convertFrom(const T& variant);
384 CPPWAMP_HIDDEN static
Variant convertFrom(const std::vector<T>& vec);
387 CPPWAMP_HIDDEN static
Variant convertFrom(const std::map<
String, T>& map);
390 CPPWAMP_HIDDEN
void convertTo(T& value) const;
393 CPPWAMP_HIDDEN
void convertTo(T& value) const;
396 CPPWAMP_HIDDEN
void convertTo(T& variant) const;
399 CPPWAMP_HIDDEN
void convertTo(std::vector<T>& vec) const;
402 CPPWAMP_HIDDEN
void convertTo(std::map<
String, T>& map) const;
404 template <typename TField, typename V>
405 CPPWAMP_HIDDEN static TField& get(V&& variant);
434 CPPWAMP_API
void swap(Variant& v, Variant& w) noexcept;
450 CPPWAMP_API
bool isNumber(
const Variant& v);
459 CPPWAMP_API
bool isScalar(
const Variant& v);
474 template <
typename TBound>
484 CPPWAMP_API std::ostream& operator<<(std::ostream& out,
const Array& a);
487 CPPWAMP_API std::ostream& operator<<(std::ostream& out,
const Object& o);
490 CPPWAMP_API std::ostream& operator<<(std::ostream& out,
const Variant& v);
493 CPPWAMP_API std::string toString(
const Array& a);
496 CPPWAMP_API std::string toString(
const Object& o);
499 CPPWAMP_API std::string toString(
const Variant& v);
523 template <
typename T>
524 CPPWAMP_API
bool operator==(
const Variant& variant,
const T& value);
529 template <
typename T>
530 CPPWAMP_API
bool operator==(
const T& value,
const Variant& variant);
536 CPPWAMP_API
bool operator==(
const Variant& variant,
544 const Variant& variant);
561 template <
typename T>
562 bool operator!=(
const Variant& variant,
const T& value);
567 template <
typename T>
568 CPPWAMP_API
bool operator!=(
const T& value,
const Variant& variant);
574 CPPWAMP_API
bool operator!=(
const Variant& variant,
582 const Variant& variant);
614 static constexpr
bool convertingToVariant =
true;
623 template <
typename T>
627 template <
typename T>
631 template <
typename T>
635 template <
typename T,
typename U>
660 static constexpr
bool convertingToVariant =
false;
672 template <
typename T>
676 template <
typename T>
680 template <
typename T>
685 template <
typename T,
typename U>
689 const Variant& variant()
const;
707 template <
typename TConverter,
typename TValue,
709 CPPWAMP_API
inline void convert(TConverter& c, TValue& val)
713 ConversionAccess::convert(c, val);
719 template <typename TEnum, EnableIf<std::is_enum<TEnum>::value> = 0>
722 using U =
typename std::underlying_type<TEnum>::type;
724 e =
static_cast<TEnum
>(n);
730 template <typename TEnum, EnableIf<std::is_enum<TEnum>::value> = 0>
733 using U =
typename std::underlying_type<TEnum>::type;
734 c.
variant() =
static_cast<U
>(e);
743 template <
typename TValue>
746 return convertFrom(std::forward<TValue>(value));
757 template <typename T, CPPWAMP_ENABLE_IF(Variant::isValidArg<T>())>
760 static_assert(ArgTraits<T>::isValid,
"Invalid argument type");
761 using FieldType =
typename ArgTraits<T>::FieldType;
762 typeId_ = FieldTraits<FieldType>::typeId;
763 constructAs<FieldType>(std::move(value));
775 static_assert(ArgTraits<T>::isValid,
"Invalid vector element type");
777 array.reserve(vec.size());
778 std::move(vec.begin(), vec.end(), std::back_inserter(
array));
779 constructAs<Array>(std::move(
array));
791 static_assert(ArgTraits<T>::isValid,
"Invalid map value type");
793 std::move(map.begin(), map.end(), std::inserter(
object,
object.begin()));
794 constructAs<Object>(std::move(
object));
800 static_assert(FieldTraits<TBound>::isValid,
"Invalid field type");
801 return typeId_ == FieldTraits<TBound>::typeId;
807 return is<BoundTypeForId<id>>();
842 T result(std::move(ConversionAccess::defaultConstruct<T>()));
864 template <
typename T>
868 return std::forward<T>(fallback);
870 return this->to< ValueTypeOf<T> >();
881 return get<TBound>(*
this);
892 return get<const TBound>(*
this);
903 return as<BoundTypeForId<id>>();
914 return as<BoundTypeForId<id>>();
927 static_assert(ArgTraits<T>::isValid,
"Invalid argument type");
929 using FieldType =
typename ArgTraits<T>::FieldType;
931 as<FieldType>() = std::move(value);
935 constructAs<FieldType>(std::move(value));
936 typeId_ = FieldTraits<FieldType>::typeId;
947 template <
typename T>
950 static_assert(ArgTraits<T>::isValid,
"Invalid vector element type");
953 array.reserve(vec.size());
954 std::move(vec.begin(), vec.end(), std::back_inserter(
array));
955 return *
this = std::move(
array);
964 template <
typename T>
967 static_assert(ArgTraits<T>::isValid,
"Invalid map value type");
969 return *
this = std::move(
object);
973 template <
typename TField,
typename TArg>
974 void Variant::constructAs(TArg&& value)
976 Access<TField>::construct(std::forward<TArg>(value), &field_);
980 template <
typename TField>
void Variant::destructAs()
982 Access<TField>::destruct(&field_);
986 template <typename T, EnableIf<Variant::isValidArg<T>()>>
987 Variant Variant::convertFrom(T&& value)
989 return Variant(std::forward<T>(value));
993 template <typename T, EnableIf<Variant::isInvalidArg<T>()>>
994 Variant Variant::convertFrom(
const T& value)
997 ToVariantConverter conv(v);
998 convert(conv,
const_cast<T&
>(value));
1003 template <typename T, EnableIf<Variant::isVariantArg<T>()>>
1004 Variant Variant::convertFrom(
const T& variant)
1010 template <typename T, EnableIf<Variant::isInvalidArg<T>()>>
1011 Variant Variant::convertFrom(
const std::vector<T>& vec)
1014 for (
const auto& elem: vec)
1015 array.emplace_back(Variant::convertFrom(elem));
1016 return Variant(std::move(array));
1020 template <typename T, EnableIf<Variant::isInvalidArg<T>()>>
1021 Variant Variant::convertFrom(
const std::map<String, T>& map)
1024 for (
const auto& kv: map)
1025 object.emplace(kv.first, Variant::convertFrom(kv.second));
1026 return Variant(std::move(
object));
1030 template <typename T, EnableIf<Variant::isValidArg<T>()>>
1031 void Variant::convertTo(T& value)
const
1037 template <typename T, EnableIf<Variant::isInvalidArg<T>()>>
1038 void Variant::convertTo(T& value)
const
1040 FromVariantConverter conv(*
this);
1045 template <typename T, EnableIf<Variant::isVariantArg<T>()>>
1046 void Variant::convertTo(T& variant)
const
1052 template <typename T, EnableIf<Variant::isInvalidArg<T>()>>
1053 void Variant::convertTo(std::vector<T>& vec)
const
1055 const auto&
array = this->as<Array>();
1056 for (
const auto& elem: array)
1059 elem.convertTo(value);
1060 vec.emplace_back(std::move(value));
1065 template <typename T, EnableIf<Variant::isInvalidArg<T>()>>
1066 void Variant::convertTo(std::map<String, T>& map)
const
1068 const auto&
object = this->as<Object>();
1069 for (
const auto& kv:
object)
1072 kv.second.convertTo(value);
1073 map.emplace(std::move(kv.first), std::move(value));
1078 template <
typename TField,
typename V> TField& Variant::get(V&& variant)
1080 using FieldType =
typename std::remove_const<TField>::type;
1081 static_assert(FieldTraits<FieldType>::isValid,
"Invalid field type");
1082 if (!variant.template is<FieldType>())
1083 throw error::Access(wamp::typeNameOf(variant),
1084 FieldTraits<FieldType>::typeName());
1085 return Access<FieldType>::get(&variant.field_);
1089 template <
typename TBound>
1092 return internal::FieldTraits<TBound>::typeName();
1096 template <
typename T>
1097 bool operator==(
const Variant& variant,
const T& value)
1099 static_assert(internal::ArgTraits<T>::isValid,
1100 "Invalid value type");
1101 return applyWithOperand(internal::VariantEquivalentTo<Variant>(), variant,
1106 template <
typename T>
1107 bool operator==(
const T& value,
const Variant& variant)
1109 return variant == value;
1113 template <
typename T>
1114 bool operator!=(
const Variant& variant,
const T& value)
1116 static_assert(internal::ArgTraits<T>::isValid,
1117 "Invalid value type");
1118 return applyWithOperand(internal::VariantNotEquivalentTo<Variant>(),
1123 template <
typename T>
1124 bool operator!=(
const T& value,
const Variant& variant)
1126 return variant != value;
1147 var_ = std::move(
array);
1156 template <
typename T>
1169 template <
typename T>
1185 template <
typename T>
1191 object.emplace( std::move(key),
1202 template <
typename T,
typename U>
1205 return operator()(std::move(key), std::forward<T>(value));
1249 template <
typename T>
1268 template <
typename T>
1273 var_.
at(index_).
to(value);
1278 std::ostringstream oss;
1279 oss << e.what() <<
", for array index " << index_;
1284 std::ostringstream oss;
1285 oss <<
"wamp::error::Conversion: Attemping to access field type "
1286 << typeNameOf(var_) <<
" as array";
1289 catch (
const std::out_of_range&)
1291 std::ostringstream oss;
1292 oss <<
"wamp::error::Conversion: Cannot extract more than " << index_
1293 <<
" elements from the array";
1312 template <
typename T>
1318 var_.
at(key).
to(value);
1322 std::ostringstream oss;
1323 oss << e.what() <<
", for object member \"" << key <<
'"';
1328 std::ostringstream oss;
1329 oss <<
"wamp::error::Conversion: Attemping to access field type "
1330 << typeNameOf(var_) <<
" as object using key \"" << key <<
'"';
1333 catch (
const std::out_of_range&)
1335 std::ostringstream oss;
1336 oss <<
"wamp::error::Conversion: Key \"" << key
1337 <<
"\" not found in object";
1353 template <
typename T,
typename U>
1355 T& value, U&& fallback)
1360 auto kv = obj.find(key);
1361 if (kv != obj.end())
1362 kv->second.to(value);
1364 value = std::forward<U>(fallback);
1368 std::ostringstream oss;
1369 oss << e.what() <<
", for object member \"" << key <<
'"';
1374 std::ostringstream oss;
1375 oss <<
"wamp::error::Conversion: Attemping to access field type "
1376 << typeNameOf(var_) <<
" as object using key \"" << key <<
'"';
1388 #ifndef CPPWAMP_COMPILED_LIB
1389 #include "internal/variant.ipp"
1392 #endif // CPPWAMP_VARIANT_HPP