summaryrefslogtreecommitdiff
path: root/boost/poly_collection/detail/type_info_map.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/poly_collection/detail/type_info_map.hpp')
-rw-r--r--boost/poly_collection/detail/type_info_map.hpp152
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;
};