File indexing completed on 2025-02-22 10:22:15
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_ALLOCATOR_ADAPTOR_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_ALLOCATOR_ADAPTOR_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/mp11/function.hpp>
0017 #include <boost/mp11/integer_sequence.hpp>
0018 #include <boost/poly_collection/detail/is_constructible.hpp>
0019 #include <new>
0020 #include <memory>
0021 #include <tuple>
0022 #include <type_traits>
0023 #include <utility>
0024
0025 namespace boost{
0026
0027 namespace poly_collection{
0028
0029 namespace detail{
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 template<typename T>
0054 class value_holder_base;
0055
0056 template<typename T>
0057 class value_holder;
0058
0059 template<typename T,typename Allocator,typename... Args>
0060 struct uses_alloc_ctor_impl
0061 {
0062 using RawAllocator=typename std::remove_cv<
0063 typename std::remove_reference<Allocator>::type
0064 >::type;
0065
0066 static const bool ua=std::uses_allocator<T,RawAllocator>::value;
0067 static const int ic=is_constructible<
0068 T,std::allocator_arg_t,Allocator,Args...>::value?1:0;
0069 static const int value=ua?2-ic:0;
0070 };
0071
0072 template<typename T,typename Allocator,typename... Args>
0073 struct uses_alloc_ctor:
0074 std::integral_constant<int,uses_alloc_ctor_impl<T,Allocator,Args...>::value>
0075 {};
0076
0077 template<typename Allocator,typename=void>
0078 struct allocator_is_always_equal:std::is_empty<Allocator>{};
0079
0080 template<typename Allocator>
0081 struct allocator_is_always_equal<
0082 Allocator,
0083 mp11::mp_void<
0084 typename std::allocator_traits<Allocator>::is_always_equal
0085 >
0086 >:std::allocator_traits<Allocator>::is_always_equal{};
0087
0088 template<typename Allocator>
0089 struct allocator_adaptor:Allocator
0090 {
0091 using traits=std::allocator_traits<Allocator>;
0092
0093 using value_type=typename traits::value_type;
0094 using size_type=typename traits::size_type;
0095 using difference_type=typename traits::difference_type;
0096 using pointer=typename traits::pointer;
0097 using const_pointer=typename traits::const_pointer;
0098 using void_pointer=typename traits::void_pointer;
0099 using const_void_pointer=typename traits::const_void_pointer;
0100 using propagate_on_container_copy_assignment=
0101 typename traits::propagate_on_container_copy_assignment;
0102 using propagate_on_container_move_assignment=
0103 typename traits::propagate_on_container_move_assignment;
0104 using propagate_on_container_swap=
0105 typename traits::propagate_on_container_swap;
0106 using is_always_equal=typename allocator_is_always_equal<Allocator>::type;
0107
0108 template<typename U>
0109 struct rebind
0110 {
0111 using other=allocator_adaptor<typename traits::template rebind_alloc<U>>;
0112 };
0113
0114 allocator_adaptor()=default;
0115 allocator_adaptor(const allocator_adaptor&)=default;
0116
0117 template<
0118 typename Allocator2,
0119 typename std::enable_if<
0120 is_constructible<Allocator,const Allocator2&>::value
0121 >::type* =nullptr
0122 >
0123 allocator_adaptor(const Allocator2& x)noexcept:Allocator{x}{}
0124
0125 template<
0126 typename Allocator2,
0127 typename std::enable_if<
0128 is_constructible<Allocator,const Allocator2&>::value
0129 >::type* =nullptr
0130 >
0131 allocator_adaptor(const allocator_adaptor<Allocator2>& x)noexcept:
0132 Allocator{x.allocator()}{}
0133
0134 allocator_adaptor& operator=(const allocator_adaptor&)=default;
0135
0136 Allocator& allocator()noexcept{return *this;}
0137 const Allocator& allocator()const noexcept{return *this;}
0138
0139 template<typename T,typename... Args>
0140 void construct(T* p,Args&&... args)
0141 {
0142 construct_(
0143 uses_alloc_ctor<T,allocator_adaptor&,Args...>{},
0144 p,std::forward<Args>(args)...);
0145 }
0146
0147 template<typename T,typename... Args>
0148 void construct(value_holder<T>* p,Args&&... args)
0149 {
0150 ::new ((void*)p) value_holder<T>(allocator(),std::forward<Args>(args)...);
0151 }
0152
0153 template<typename T1,typename T2,typename... Args1,typename... Args2>
0154 void construct(
0155 std::pair<T1,T2>* p,std::piecewise_construct_t,
0156 std::tuple<Args1...> x,std::tuple<Args2...> y)
0157 {
0158 ::new ((void*)p) std::pair<T1,T2>(
0159 std::piecewise_construct,
0160 transform_tuple(
0161 uses_alloc_ctor<T1,allocator_adaptor&,Args1...>{},
0162 std::move(x),
0163 mp11::make_index_sequence<sizeof...(Args1)>{}),
0164 transform_tuple(
0165 uses_alloc_ctor<T2,allocator_adaptor&,Args2...>{},
0166 std::move(y),
0167 mp11::make_index_sequence<sizeof...(Args2)>{})
0168 );
0169 }
0170
0171 template<typename T1,typename T2>
0172 void construct(std::pair<T1,T2>* p)
0173 {
0174 construct(p,std::piecewise_construct,std::tuple<>{},std::tuple<>{});
0175 }
0176
0177 template<typename T1,typename T2,typename U,typename V>
0178 void construct(std::pair<T1,T2>* p,U&& x,V&& y)
0179 {
0180 construct(
0181 p,std::piecewise_construct,
0182 std::forward_as_tuple(std::forward<U>(x)),
0183 std::forward_as_tuple(std::forward<V>(y)));
0184 }
0185
0186 template<typename T1,typename T2,typename U,typename V>
0187 void construct(std::pair<T1,T2>* p,const std::pair<U,V>& x)
0188 {
0189 construct(
0190 p,std::piecewise_construct,
0191 std::forward_as_tuple(x.first),std::forward_as_tuple(x.second));
0192 }
0193
0194 template<typename T1,typename T2,typename U,typename V>
0195 void construct(std::pair<T1,T2>* p,std::pair<U,V>&& x)
0196 {
0197 construct(
0198 p,std::piecewise_construct,
0199 std::forward_as_tuple(std::forward<U>(x.first)),
0200 std::forward_as_tuple(std::forward<V>(x.second)));
0201 }
0202
0203 template<typename T>
0204 void destroy(T* p)
0205 {
0206 p->~T();
0207 }
0208
0209 template<typename T>
0210 void destroy(value_holder<T>* p)
0211 {
0212 traits::destroy(
0213 allocator(),
0214 reinterpret_cast<T*>(static_cast<value_holder_base<T>*>(p)));
0215 }
0216
0217 allocator_adaptor
0218 select_on_container_copy_construction()const noexcept
0219 {
0220 return traits::select_on_container_copy_construction(allocator());
0221 }
0222
0223 private:
0224 template<typename T,typename... Args>
0225 void construct_(
0226 std::integral_constant<int,0>,
0227 T* p,Args&&... args)
0228 {
0229 ::new ((void*)p) T(std::forward<Args>(args)...);
0230 }
0231
0232 template<typename T,typename... Args>
0233 void construct_(
0234 std::integral_constant<int,1>,
0235 T* p,Args&&... args)
0236 {
0237 ::new ((void*)p) T(std::allocator_arg,*this,std::forward<Args>(args)...);
0238 }
0239
0240 template<typename T,typename... Args>
0241 void construct_(
0242 std::integral_constant<int,2>,
0243 T* p,Args&&... args)
0244 {
0245 ::new ((void*)p) T(std::forward<Args>(args)...,*this);
0246 }
0247
0248 template<typename... Args,std::size_t... I>
0249 std::tuple<Args&&...> transform_tuple(
0250 std::integral_constant<int,0>,
0251 std::tuple<Args...>&& t,mp11::index_sequence<I...>)
0252 {
0253 return std::tuple<Args&&...>(std::get<I>(std::move(t))...);
0254 }
0255
0256 template<typename... Args,std::size_t... I>
0257 std::tuple<std::allocator_arg_t,allocator_adaptor&,Args&&...>
0258 transform_tuple(
0259 std::integral_constant<int,1>,
0260 std::tuple<Args...>&& t,mp11::index_sequence<I...>)
0261 {
0262 return std::tuple<
0263 std::allocator_arg_t,allocator_adaptor&,Args&&...>(
0264 std::allocator_arg,*this,std::get<I>(std::move(t))...);
0265 }
0266
0267 template<typename... Args,std::size_t... I>
0268 std::tuple<Args&&...,allocator_adaptor&>
0269 transform_tuple(
0270 std::integral_constant<int,2>,
0271 std::tuple<Args...>&& t,mp11::index_sequence<I...>)
0272 {
0273 return std::tuple<Args&&...,allocator_adaptor&>(
0274 std::get<I>(std::move(t))...,*this);
0275 }
0276 };
0277
0278 template<typename Allocator1,typename Allocator2>
0279 bool operator==(
0280 const allocator_adaptor<Allocator1>& x,
0281 const allocator_adaptor<Allocator2>& y)noexcept
0282 {
0283 return x.allocator()==y.allocator();
0284 }
0285
0286 template<typename Allocator1,typename Allocator2>
0287 bool operator!=(
0288 const allocator_adaptor<Allocator1>& x,
0289 const allocator_adaptor<Allocator2>& y)noexcept
0290 {
0291 return !(x==y);
0292 }
0293
0294 }
0295
0296 }
0297
0298 }
0299
0300 #endif