Added a MapItem to wrap key/value pairs

This commit is contained in:
Randolph Voorhies
2013-07-03 20:05:34 -07:00
parent 3885d8b537
commit d24c0e2db2
3 changed files with 101 additions and 9 deletions

View File

@@ -99,7 +99,9 @@ namespace cereal
cereal::make_nvp<Archive>(b) );
}
};
@endcode */
@endcode
@internal */
template <class T>
class NameValuePair : detail::NameValuePairCore
{
@@ -121,7 +123,8 @@ namespace cereal
the value can be both loaded and saved to. If you pass an r-value reference,
the NameValuePair will store a copy of it instead of a reference. Thus you should
only pass r-values in cases where this makes sense, such as the result of some
size() call. In either case, any constness will be stripped away */
size() call. In either case, any constness will be stripped away
@internal */
NameValuePair( char const * n, T && v ) : name(n), value(const_cast<Type>(v)) {}
char const * name;
@@ -129,7 +132,8 @@ namespace cereal
};
//! A specialization of make_nvp<> that simply forwards the value for binary archives
/*! @relates NameValuePair */
/*! @relates NameValuePair
@internal */
template<class Archive, class T>
typename
std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
@@ -141,7 +145,8 @@ namespace cereal
}
//! A specialization of make_nvp<> that actually creates an nvp for non-binary archives
/*! @relates NameValuePair */
/*! @relates NameValuePair
@internal */
template<class Archive, class T>
typename
std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
@@ -157,7 +162,9 @@ namespace cereal
//! A wrapper around data that can be serialized in a binary fashion
/*! This class is used to demarcate data that can safely be serialized
as a binary chunk of data. Individual archives can then choose how
best represent this during serialization. */
best represent this during serialization.
@internal */
template <class T>
struct BinaryData
{
@@ -195,7 +202,9 @@ namespace cereal
they choose to serialize size metadata for containers. For some archive
types, the size may be implicitly encoded in the output (e.g. JSON) and
not need an explicit entry. Specializing serialize or load/save for
your archive and SizeTags allows you to choose what happens */
your archive and SizeTags allows you to choose what happens
@internal */
template <class T>
class SizeTag
{
@@ -212,6 +221,69 @@ namespace cereal
Type size;
};
// ######################################################################
//! A wrapper around a key and value for serializing data into maps.
/*! This class just provides a grouping of keys and values into a struct for
human readable archives. For example, XML archives will use this wrapper
to write maps like so:
@code{.xml}
<mymap>
<item0>
<key>MyFirstKey</key>
<value>MyFirstValue</value>
</item0>
<item1>
<key>MySecondKey</key>
<value>MySecondValue</value>
</item1>
</mymap>
@endcode
\sa make_map_item
@internal */
template <class Key, class Value>
struct MapItem
{
using DecayKey = typename std::decay<Key>::type;
using KeyType = typename std::conditional<
std::is_rvalue_reference<Key>::value,
DecayKey,
typename std::add_lvalue_reference<DecayKey>::type>::type;
using DecayValue = typename std::decay<Value>::type;
using ValueType = typename std::conditional<
std::is_rvalue_reference<Value>::value,
DecayValue,
typename std::add_lvalue_reference<DecayValue>::type>::type;
//! Construct a MapItem from a key and a value
/*! @internal */
MapItem( Key && key, Value && value ) : key(const_cast<KeyType>(key)), value(const_cast<ValueType>(value)) {}
KeyType key;
ValueType value;
//! Serialize the MapItem with the NVPs "key" and "value"
template<class Archive>
void serialize(Archive & archive)
{
archive( make_nvp<Archive>("key", key),
make_nvp<Archive>("value", value) );
}
};
//! Create a MapItem so that human readable archives will group keys and values together
/*! @internal
@relates MapItem */
template<class KeyType, class ValueType>
MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
{
return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
}
} // namespace cereal
#endif // CEREAL_DETAILS_HELPERS_HPP_

View File

@@ -30,6 +30,7 @@
#include <cereal/cereal.hpp>
#include <map>
namespace cereal
{
namespace map_detail
@@ -40,7 +41,9 @@ namespace cereal
ar( make_size_tag( map.size() ) );
for( const auto & i : map )
ar( i.first, i.second );
{
ar( ::cereal::make_map_item(i.first, i.second) );
}
}
template <class Archive, class MapT> inline
@@ -57,7 +60,7 @@ namespace cereal
typename MapT::key_type key;
typename MapT::mapped_type value;
ar( key, value );
ar( ::cereal::make_map_item(key, value) );
hint = map.insert(hint, {key, value} );
}
}

View File

@@ -299,9 +299,9 @@ int main()
assert(e_in == e_out);
{
//std::stringstream os;
std::ofstream os("out.xml");
cereal::XMLOutputArchive oar( os );
//cereal::XMLOutputArchive oar( std::cout );
oar( cereal::make_nvp("hello", 5 ) );
@@ -311,6 +311,15 @@ int main()
auto intptr = std::make_shared<int>(99);
oar( CEREAL_NVP(intptr) );
std::map<std::string, int> map1 =
{
{"one", 1},
{"two", 2},
{"three", 3}
};
oar( CEREAL_NVP(map1) );
int x = 3;
oar( CEREAL_NVP(x) );
oar( 5 );
@@ -353,6 +362,14 @@ int main()
iar( CEREAL_NVP(intptr) );
assert( *intptr == 99 );
std::map<std::string, int> map1;
iar( CEREAL_NVP(map1) );
assert( map1["one"] == 1 );
assert( map1["two"] == 2 );
assert( map1["three"] == 3 );
int x;
iar( CEREAL_NVP(x) );
assert( x == 3 );