Improved templates for std::unordered_map and std::unordered_set so they handle all sorts of those

This commit is contained in:
Vladyslav Frolov 2015-07-31 04:16:14 -07:00
parent 7e6a498c14
commit f986370634
2 changed files with 68 additions and 68 deletions

View File

@ -32,15 +32,15 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct as< struct as<
std::unordered_map<K, V>, std::unordered_map<K, V, OtherTypes...>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> { typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
std::unordered_map<K, V> operator()(msgpack::object const& o) const { std::unordered_map<K, V, OtherTypes...> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr); msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::unordered_map<K, V> v; std::unordered_map<K, V, OtherTypes...> v;
for (; p != pend; ++p) { for (; p != pend; ++p) {
v.emplace(p->key.as<K>(), p->val.as<V>()); v.emplace(p->key.as<K>(), p->val.as<V>());
} }
@ -48,13 +48,13 @@ struct as<
} }
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct convert<std::unordered_map<K, V>> { struct convert<std::unordered_map<K, V, OtherTypes...>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_map<K, V>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_map<K, V, OtherTypes...>& v) const {
if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr); msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::unordered_map<K, V> tmp; std::unordered_map<K, V, OtherTypes...> tmp;
for(; p != pend; ++p) { for(; p != pend; ++p) {
K key; K key;
p->key.convert(key); p->key.convert(key);
@ -65,13 +65,13 @@ struct convert<std::unordered_map<K, V>> {
} }
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct pack<std::unordered_map<K, V>> { struct pack<std::unordered_map<K, V, OtherTypes...>> {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_map<K,V>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_map<K, V, OtherTypes...>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_map(size); o.pack_map(size);
for(typename std::unordered_map<K,V>::const_iterator it(v.begin()), it_end(v.end()); for(typename std::unordered_map<K, V, OtherTypes...>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(it->first); o.pack(it->first);
o.pack(it->second); o.pack(it->second);
@ -80,9 +80,9 @@ struct pack<std::unordered_map<K, V>> {
} }
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct object_with_zone<std::unordered_map<K, V>> { struct object_with_zone<std::unordered_map<K, V, OtherTypes...>> {
void operator()(msgpack::object::with_zone& o, const std::unordered_map<K,V>& v) const { void operator()(msgpack::object::with_zone& o, const std::unordered_map<K, V, OtherTypes...>& v) const {
o.type = msgpack::type::MAP; o.type = msgpack::type::MAP;
if(v.empty()) { if(v.empty()) {
o.via.map.ptr = nullptr; o.via.map.ptr = nullptr;
@ -93,7 +93,7 @@ struct object_with_zone<std::unordered_map<K, V>> {
msgpack::object_kv* const pend = p + size; msgpack::object_kv* const pend = p + size;
o.via.map.ptr = p; o.via.map.ptr = p;
o.via.map.size = size; o.via.map.size = size;
typename std::unordered_map<K,V>::const_iterator it(v.begin()); typename std::unordered_map<K, V, OtherTypes...>::const_iterator it(v.begin());
do { do {
p->key = msgpack::object(it->first, o.zone); p->key = msgpack::object(it->first, o.zone);
p->val = msgpack::object(it->second, o.zone); p->val = msgpack::object(it->second, o.zone);
@ -105,15 +105,15 @@ struct object_with_zone<std::unordered_map<K, V>> {
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct as< struct as<
std::unordered_multimap<K, V>, std::unordered_multimap<K, V, OtherTypes...>,
typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> { typename std::enable_if<msgpack::has_as<K>::value && msgpack::has_as<V>::value>::type> {
std::unordered_multimap<K, V> operator()(msgpack::object const& o) const { std::unordered_multimap<K, V, OtherTypes...> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr); msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::unordered_multimap<K, V> v; std::unordered_multimap<K, V, OtherTypes...> v;
for (; p != pend; ++p) { for (; p != pend; ++p) {
v.emplace(p->key.as<K>(), p->val.as<V>()); v.emplace(p->key.as<K>(), p->val.as<V>());
} }
@ -121,13 +121,13 @@ struct as<
} }
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct convert<std::unordered_multimap<K, V>> { struct convert<std::unordered_multimap<K, V, OtherTypes...>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_multimap<K, V>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_multimap<K, V, OtherTypes...>& v) const {
if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); } if(o.type != msgpack::type::MAP) { throw msgpack::type_error(); }
msgpack::object_kv* p(o.via.map.ptr); msgpack::object_kv* p(o.via.map.ptr);
msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size); msgpack::object_kv* const pend(o.via.map.ptr + o.via.map.size);
std::unordered_multimap<K, V> tmp; std::unordered_multimap<K, V, OtherTypes...> tmp;
for(; p != pend; ++p) { for(; p != pend; ++p) {
std::pair<K, V> value; std::pair<K, V> value;
p->key.convert(value.first); p->key.convert(value.first);
@ -139,13 +139,13 @@ struct convert<std::unordered_multimap<K, V>> {
} }
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct pack<std::unordered_multimap<K, V>> { struct pack<std::unordered_multimap<K, V, OtherTypes...>> {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_multimap<K,V>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_multimap<K, V, OtherTypes...>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_map(size); o.pack_map(size);
for(typename std::unordered_multimap<K,V>::const_iterator it(v.begin()), it_end(v.end()); for(typename std::unordered_multimap<K, V, OtherTypes...>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(it->first); o.pack(it->first);
o.pack(it->second); o.pack(it->second);
@ -154,9 +154,9 @@ struct pack<std::unordered_multimap<K, V>> {
} }
}; };
template <typename K, typename V> template <typename K, typename V, typename... OtherTypes>
struct object_with_zone<std::unordered_multimap<K, V>> { struct object_with_zone<std::unordered_multimap<K, V, OtherTypes...>> {
void operator()(msgpack::object::with_zone& o, const std::unordered_multimap<K,V>& v) const { void operator()(msgpack::object::with_zone& o, const std::unordered_multimap<K, V, OtherTypes...>& v) const {
o.type = msgpack::type::MAP; o.type = msgpack::type::MAP;
if(v.empty()) { if(v.empty()) {
o.via.map.ptr = nullptr; o.via.map.ptr = nullptr;
@ -167,7 +167,7 @@ struct object_with_zone<std::unordered_multimap<K, V>> {
msgpack::object_kv* const pend = p + size; msgpack::object_kv* const pend = p + size;
o.via.map.ptr = p; o.via.map.ptr = p;
o.via.map.size = size; o.via.map.size = size;
typename std::unordered_multimap<K,V>::const_iterator it(v.begin()); typename std::unordered_multimap<K, V, OtherTypes...>::const_iterator it(v.begin());
do { do {
p->key = msgpack::object(it->first, o.zone); p->key = msgpack::object(it->first, o.zone);
p->val = msgpack::object(it->second, o.zone); p->val = msgpack::object(it->second, o.zone);

View File

@ -32,44 +32,44 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
template <typename T> template <typename Key, typename... OtherTypes>
struct as<std::unordered_set<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> { struct as<std::unordered_set<Key, OtherTypes...>, typename std::enable_if<msgpack::has_as<Key>::value>::type> {
std::unordered_set<T> operator()(msgpack::object const& o) const { std::unordered_set<Key, OtherTypes...> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size; msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr; msgpack::object* const pbegin = o.via.array.ptr;
std::unordered_set<T> v; std::unordered_set<Key, OtherTypes...> v;
while (p > pbegin) { while (p > pbegin) {
--p; --p;
v.insert(p->as<T>()); v.insert(p->as<Key>());
} }
return v; return v;
} }
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct convert<std::unordered_set<T>> { struct convert<std::unordered_set<Key, OtherTypes...>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_set<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_set<Key, OtherTypes...>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size; msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr; msgpack::object* const pbegin = o.via.array.ptr;
std::unordered_set<T> tmp; std::unordered_set<Key, OtherTypes...> tmp;
while(p > pbegin) { while(p > pbegin) {
--p; --p;
tmp.insert(p->as<T>()); tmp.insert(p->as<Key>());
} }
v = std::move(tmp); v = std::move(tmp);
return o; return o;
} }
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct pack<std::unordered_set<T>> { struct pack<std::unordered_set<Key, OtherTypes...>> {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_set<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_set<Key, OtherTypes...>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for(typename std::unordered_set<T>::const_iterator it(v.begin()), it_end(v.end()); for(typename std::unordered_set<Key, OtherTypes...>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(*it); o.pack(*it);
} }
@ -77,9 +77,9 @@ struct pack<std::unordered_set<T>> {
} }
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct object_with_zone<std::unordered_set<T>> { struct object_with_zone<std::unordered_set<Key, OtherTypes...>> {
void operator()(msgpack::object::with_zone& o, const std::unordered_set<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::unordered_set<Key, OtherTypes...>& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
if(v.empty()) { if(v.empty()) {
o.via.array.ptr = nullptr; o.via.array.ptr = nullptr;
@ -90,7 +90,7 @@ struct object_with_zone<std::unordered_set<T>> {
msgpack::object* const pend = p + size; msgpack::object* const pend = p + size;
o.via.array.ptr = p; o.via.array.ptr = p;
o.via.array.size = size; o.via.array.size = size;
typename std::unordered_set<T>::const_iterator it(v.begin()); typename std::unordered_set<Key, OtherTypes...>::const_iterator it(v.begin());
do { do {
*p = msgpack::object(*it, o.zone); *p = msgpack::object(*it, o.zone);
++p; ++p;
@ -101,44 +101,44 @@ struct object_with_zone<std::unordered_set<T>> {
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct as<std::unordered_multiset<T>, typename std::enable_if<msgpack::has_as<T>::value>::type> { struct as<std::unordered_multiset<Key, OtherTypes...>, typename std::enable_if<msgpack::has_as<Key>::value>::type> {
std::unordered_multiset<T> operator()(msgpack::object const& o) const { std::unordered_multiset<Key, OtherTypes...> operator()(msgpack::object const& o) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size; msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr; msgpack::object* const pbegin = o.via.array.ptr;
std::unordered_multiset<T> v; std::unordered_multiset<Key, OtherTypes...> v;
while (p > pbegin) { while (p > pbegin) {
--p; --p;
v.insert(p->as<T>()); v.insert(p->as<Key>());
} }
return v; return v;
} }
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct convert<std::unordered_multiset<T>> { struct convert<std::unordered_multiset<Key, OtherTypes...>> {
msgpack::object const& operator()(msgpack::object const& o, std::unordered_multiset<T>& v) const { msgpack::object const& operator()(msgpack::object const& o, std::unordered_multiset<Key, OtherTypes...>& v) const {
if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
msgpack::object* p = o.via.array.ptr + o.via.array.size; msgpack::object* p = o.via.array.ptr + o.via.array.size;
msgpack::object* const pbegin = o.via.array.ptr; msgpack::object* const pbegin = o.via.array.ptr;
std::unordered_multiset<T> tmp; std::unordered_multiset<Key, OtherTypes...> tmp;
while(p > pbegin) { while(p > pbegin) {
--p; --p;
tmp.insert(p->as<T>()); tmp.insert(p->as<Key>());
} }
v = std::move(tmp); v = std::move(tmp);
return o; return o;
} }
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct pack<std::unordered_multiset<T>> { struct pack<std::unordered_multiset<Key, OtherTypes...>> {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_multiset<T>& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const std::unordered_multiset<Key, OtherTypes...>& v) const {
uint32_t size = checked_get_container_size(v.size()); uint32_t size = checked_get_container_size(v.size());
o.pack_array(size); o.pack_array(size);
for(typename std::unordered_multiset<T>::const_iterator it(v.begin()), it_end(v.end()); for(typename std::unordered_multiset<Key, OtherTypes...>::const_iterator it(v.begin()), it_end(v.end());
it != it_end; ++it) { it != it_end; ++it) {
o.pack(*it); o.pack(*it);
} }
@ -146,9 +146,9 @@ struct pack<std::unordered_multiset<T>> {
} }
}; };
template <typename T> template <typename Key, typename... OtherTypes>
struct object_with_zone<std::unordered_multiset<T>> { struct object_with_zone<std::unordered_multiset<Key, OtherTypes...>> {
void operator()(msgpack::object::with_zone& o, const std::unordered_multiset<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::unordered_multiset<Key, OtherTypes...>& v) const {
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;
if(v.empty()) { if(v.empty()) {
o.via.array.ptr = nullptr; o.via.array.ptr = nullptr;
@ -159,7 +159,7 @@ struct object_with_zone<std::unordered_multiset<T>> {
msgpack::object* const pend = p + size; msgpack::object* const pend = p + size;
o.via.array.ptr = p; o.via.array.ptr = p;
o.via.array.size = size; o.via.array.size = size;
typename std::unordered_multiset<T>::const_iterator it(v.begin()); typename std::unordered_multiset<Key, OtherTypes...>::const_iterator it(v.begin());
do { do {
*p = msgpack::object(*it, o.zone); *p = msgpack::object(*it, o.zone);
++p; ++p;