diff options
Diffstat (limited to 'boost/poly_collection/detail/type_info_map.hpp')
-rw-r--r-- | boost/poly_collection/detail/type_info_map.hpp | 152 |
1 files changed, 100 insertions, 52 deletions
diff --git a/boost/poly_collection/detail/type_info_map.hpp b/boost/poly_collection/detail/type_info_map.hpp index 43dd6ddfc8..fcc6a8cef5 100644 --- a/boost/poly_collection/detail/type_info_map.hpp +++ b/boost/poly_collection/detail/type_info_map.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2017 Joaquin M Lopez Munoz. +/* Copyright 2016-2018 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) @@ -14,8 +14,9 @@ #endif #include <boost/detail/workaround.hpp> -#include <boost/poly_collection/detail/newdelete_allocator.hpp> #include <functional> +#include <memory> +#include <type_traits> #include <typeinfo> #include <unordered_map> #include <utility> @@ -49,7 +50,6 @@ struct type_info_ptr_equal_to {return *p==*q;} }; - template<typename T,typename Allocator> class type_info_map { @@ -68,70 +68,70 @@ public: using iterator=typename map_type::iterator; using const_iterator=typename map_type::const_iterator; -#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) - /* std::unordered_map(const unordered_map&,const allocator_type&), - * std::unordered_map(unordered_map&&,const allocator_type&) and - * std::unordered_map(const allocator_type&) not available. - */ - -#define BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(x,al) \ -x.begin(),x.end(), \ -0,typename map_type::hasher{},typename map_type::key_equal{},al -#define BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR(al) \ -10,typename map_type::hasher{},typename map_type::key_equal{},al -#define BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(al) \ -10,typename cache_type::hasher{},typename cache_type::key_equal{},al - -#else - -#define BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(x,al) x,al -#define BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR(al) al -#define BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(al) al - -#endif - type_info_map()=default; type_info_map(const type_info_map& x): map{x.map}, - cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(x.cache.get_allocator())} + cache{make<cache_type>(std::allocator_traits<cache_allocator_type>:: + select_on_container_copy_construction(x.cache.get_allocator()))} {build_cache(x.cache);} type_info_map(type_info_map&& x)=default; type_info_map(const allocator_type& al): - map{BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR(al)}, - cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(cache_allocator_type{al})} - {} + map{make<map_type>(al)},cache{make<cache_type>(al)}{} type_info_map(const type_info_map& x,const allocator_type& al): - map{BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(x.map,al)}, - cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(cache_allocator_type{al})} + map{make(x.map,al)},cache{make<cache_type>(al)} {build_cache(x.cache);} type_info_map(type_info_map&& x,const allocator_type& al): - map{BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(std::move(x.map),al)}, - cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(cache_allocator_type{al})} - { - if(al==x.map.get_allocator()&& - cache_allocator_type{al}==x.cache.get_allocator()){ - cache=std::move(x.cache); + map{make(std::move(x.map),al)}, + cache{ + al==allocator_type{x.map.get_allocator()}&&x.map.empty()? + make(std::move(x.cache),al): + make<cache_type>(al) } - else{ + { + if(!(al==allocator_type{x.map.get_allocator()}&&x.map.empty())){ build_cache(x.cache); - x.cache.clear(); } + x.map.clear(); + x.cache.clear(); } -#undef BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR -#undef BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR -#undef BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR - type_info_map& operator=(const type_info_map& x) { - if(this!=&x){ - type_info_map c{x}; - swap(c); + if(this!=&x)try{ + map=x.map; + cache=make<cache_type>(map.get_allocator()); + build_cache(x.cache); + } + catch(...){ + map.clear(); + cache.clear(); + throw; } return *this; } - type_info_map& operator=(type_info_map&& x)=default; + type_info_map& operator=(type_info_map&& x) + { + if(this!=&x)try{ + map=std::move(x.map); + if(map.get_allocator()==x.map.get_allocator()){ + cache=std::move(x.cache); + } + else{ + cache=make<cache_type>(map.get_allocator()); + build_cache(x.cache); + x.cache.clear(); + } + } + catch(...){ + map.clear(); + cache.clear(); + x.map.clear(); + x.cache.clear(); + throw; + } + return *this; + } allocator_type get_allocator()const noexcept{return map.get_allocator();} @@ -161,7 +161,9 @@ x.begin(),x.end(), \ template<typename P> std::pair<iterator,bool> insert(const key_type& key,P&& x) { - auto p=map.insert({&key,std::forward<P>(x)}); + auto c=map.bucket_count(); + auto p=map.emplace(&key,std::forward<P>(x)); + if(map.bucket_count()!=c)rebuild_cache(); cache.insert({&key,p.first}); return p; } @@ -172,18 +174,64 @@ private: using cache_type=std::unordered_map< const std::type_info*,iterator, std::hash<const std::type_info*>,std::equal_to<const std::type_info*>, - newdelete_allocator_adaptor< - typename std::allocator_traits<Allocator>::template - rebind_alloc<std::pair<const std::type_info* const,iterator>> - > + typename std::allocator_traits<Allocator>::template + rebind_alloc<std::pair<const std::type_info* const,iterator>> >; using cache_allocator_type=typename cache_type::allocator_type; +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) + /* std::unordered_map(const allocator_type&), + * std::unordered_map(const unordered_map&,const allocator_type&) and + * std::unordered_map(unordered_map&&,const allocator_type&) not available. + * We make move construction decay to copy construction. + */ + + template<typename UnorderedMap> + static UnorderedMap make(const typename UnorderedMap::allocator_type& al) + { + return UnorderedMap{ + 10,typename UnorderedMap::hasher{},typename UnorderedMap::key_equal{},al + }; + } + + template<typename UnorderedMap> + static typename std::decay<UnorderedMap>::type make( + UnorderedMap&& x, + const typename std::decay<UnorderedMap>::type::allocator_type& al) + { + using RawUnorderedMap=typename std::decay<UnorderedMap>::type; + + return RawUnorderedMap{ + x.begin(),x.end(),0,typename RawUnorderedMap::hasher{}, + typename RawUnorderedMap::key_equal{},al + }; + } +#else + template<typename UnorderedMap> + static UnorderedMap make(const typename UnorderedMap::allocator_type& al) + { + return UnorderedMap{al}; + } + + template<typename UnorderedMap> + static typename std::decay<UnorderedMap>::type make( + UnorderedMap&& x, + const typename std::decay<UnorderedMap>::type::allocator_type& al) + { + return {std::forward<UnorderedMap>(x),al}; + } +#endif + void build_cache(const cache_type& x) { for(const auto& p:x)cache.insert({p.first,map.find(p.first)}); } + void rebuild_cache() + { + for(auto& p:cache)p.second=map.find(p.first); + } + map_type map; cache_type cache; }; |