From f77229471a8ee7c1e0b8b622de21ed86389851ac Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 29 Oct 2018 23:21:07 +0100 Subject: [PATCH] Allow to teat custom types as std::map/std::set --- README.md | 2 ++ lib/tests/traits.cpp | 24 +++++++++++++++++++++++- lib/traits.h | 35 ++++++++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4ffe3ef..ca51fbb 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ The following table shows the mapping of supported C++ types to supported JSON t is currently not supported. * custom types must provide a default constructor. * constant member variables are skipped. +* It is possible to treat custom types as set/map using the macro `REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH`, + `REFLECTIVE_RAPIDJSON_TREAT_AS_SET` or `REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET`. * For custom (de)serialization, see the section below. * The binary (de)serializer supports approximately the same C++ types but obviously maps them to a platform independent binary representation rather than a JSON type. diff --git a/lib/tests/traits.cpp b/lib/tests/traits.cpp index 9b66cd3..b41bb4c 100644 --- a/lib/tests/traits.cpp +++ b/lib/tests/traits.cpp @@ -6,6 +6,15 @@ using namespace std; using namespace ReflectiveRapidJSON; +// treat some types differently to test Treat... traits +struct Foo { +}; +struct Bar { +}; +REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH(Foo); +REFLECTIVE_RAPIDJSON_TREAT_AS_SET(Bar); +REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET(Foo); + // test traits static_assert(IsArray>::value, "vector mapped to array"); static_assert(IsArray>::value, "list mapped to array"); @@ -13,9 +22,22 @@ static_assert(!IsArray>::value, "set not considered an array"); static_assert(!IsArray>::value, "multiset not considered an array"); static_assert(IsArrayOrSet>::value, "set is array or set"); static_assert(IsArrayOrSet>::value, "multiset is array or set"); -static_assert(IsSet>::value, "set"); +static_assert(IsArrayOrSet::value, "Foo is array or set via TreatAsMultiSet"); +static_assert(IsArrayOrSet::value, "Foo is array or set via TreatAsSet"); +static_assert(!IsArrayOrSet::value, "string not mapped to array or set though it is iteratable"); +static_assert(IsSet>::value, "set mapped to set"); +static_assert(IsSet>::value, "unordered_set mapped to set"); +static_assert(IsSet::value, "Bar mapped to set via TreatAsSet"); +static_assert(!IsSet::value, "string not mapped to set"); static_assert(IsMultiSet>::value, "multiset"); +static_assert(IsMultiSet::value, "Foo mapped to multiset via TreatAsMultiSet"); +static_assert(!IsMultiSet::value, "string not mapped to multiset"); static_assert(!IsArray::value, "string not mapped to array though it is iteratable"); static_assert(IsMapOrHash>::value, "map mapped to object"); static_assert(IsMapOrHash>::value, "hash mapped to object"); static_assert(!IsMapOrHash>::value, "vector not mapped to object"); +static_assert(IsMapOrHash::value, "Foo mapped to object via TreatAsMapOrHash"); +static_assert(IsIteratableExceptString>::value, "vector is iteratable"); +static_assert(!IsIteratableExceptString::value, "string not iteratable"); +static_assert(!IsIteratableExceptString::value, "wstring not iteratable"); +static_assert(!IsIteratableExceptString::value, "string not iteratable"); diff --git a/lib/traits.h b/lib/traits.h index b6b048a..db7c629 100644 --- a/lib/traits.h +++ b/lib/traits.h @@ -11,15 +11,40 @@ namespace ReflectiveRapidJSON { +// define structs and macros to allow treating custom data types as std::map, std::set, ... +/// \brief \brief The TreatAsMapOrHash class allows treating custom classes as std::map or std::unordered_map. +template struct TreatAsMapOrHash : public Traits::Bool { +}; +/// \brief \brief The TreatAsSet class allows treating custom classes as std::set or std::unordered_set. +template struct TreatAsSet : public Traits::Bool { +}; +/// \brief \brief The TreatAsMultiSet class allows treating custom classes as std::multiset or std::unordered_multiset. +template struct TreatAsMultiSet : public Traits::Bool { +}; + +#define REFLECTIVE_RAPIDJSON_TREAT_AS_MAP_OR_HASH(T) \ + template <> struct TreatAsMapOrHash : public Traits::Bool { \ + } +#define REFLECTIVE_RAPIDJSON_TREAT_AS_SET(T) \ + template <> struct TreatAsSet : public Traits::Bool { \ + } +#define REFLECTIVE_RAPIDJSON_TREAT_AS_MULTI_SET(T) \ + template <> struct TreatAsMultiSet : public Traits::Bool { \ + } + // define traits to check for arrays, sets and maps template -using IsMapOrHash = Traits::Any, Traits::IsSpecializationOf>; -template using IsSet = Traits::Any, Traits::IsSpecializationOf>; +using IsMapOrHash + = Traits::Any, Traits::IsSpecializationOf, TreatAsMapOrHash>; template -using IsMultiSet = Traits::Any, Traits::IsSpecializationOf>; +using IsSet = Traits::Any, Traits::IsSpecializationOf, TreatAsSet>; template -using IsArrayOrSet - = Traits::All, Traits::Not>, Traits::Not>>; +using IsMultiSet + = Traits::Any, Traits::IsSpecializationOf, TreatAsMultiSet>; +template +using IsArrayOrSet = Traits::Any, Traits::Not>, + Traits::Not>, Traits::Not>>, + TreatAsSet, TreatAsMultiSet>; template using IsArray = Traits::All, Traits::Not>, Traits::Not>, Traits::Not>, Traits::Not>>;