File indexing completed on 2025-09-17 08:45:56
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,typename U>
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 U,typename... Args>
0148 void construct(value_holder<T,U>* p,Args&&... args)
0149 {
0150 ::new ((void*)p) value_holder<T,U>(
0151 allocator(),std::forward<Args>(args)...);
0152 }
0153
0154 template<typename T1,typename T2,typename... Args1,typename... Args2>
0155 void construct(
0156 std::pair<T1,T2>* p,std::piecewise_construct_t,
0157 std::tuple<Args1...> x,std::tuple<Args2...> y)
0158 {
0159 ::new ((void*)p) std::pair<T1,T2>(
0160 std::piecewise_construct,
0161 transform_tuple(
0162 uses_alloc_ctor<T1,allocator_adaptor&,Args1...>{},
0163 std::move(x),
0164 mp11::make_index_sequence<sizeof...(Args1)>{}),
0165 transform_tuple(
0166 uses_alloc_ctor<T2,allocator_adaptor&,Args2...>{},
0167 std::move(y),
0168 mp11::make_index_sequence<sizeof...(Args2)>{})
0169 );
0170 }
0171
0172 template<typename T1,typename T2>
0173 void construct(std::pair<T1,T2>* p)
0174 {
0175 construct(p,std::piecewise_construct,std::tuple<>{},std::tuple<>{});
0176 }
0177
0178 template<typename T1,typename T2,typename U,typename V>
0179 void construct(std::pair<T1,T2>* p,U&& x,V&& y)
0180 {
0181 construct(
0182 p,std::piecewise_construct,
0183 std::forward_as_tuple(std::forward<U>(x)),
0184 std::forward_as_tuple(std::forward<V>(y)));
0185 }
0186
0187 template<typename T1,typename T2,typename U,typename V>
0188 void construct(std::pair<T1,T2>* p,const std::pair<U,V>& x)
0189 {
0190 construct(
0191 p,std::piecewise_construct,
0192 std::forward_as_tuple(x.first),std::forward_as_tuple(x.second));
0193 }
0194
0195 template<typename T1,typename T2,typename U,typename V>
0196 void construct(std::pair<T1,T2>* p,std::pair<U,V>&& x)
0197 {
0198 construct(
0199 p,std::piecewise_construct,
0200 std::forward_as_tuple(std::forward<U>(x.first)),
0201 std::forward_as_tuple(std::forward<V>(x.second)));
0202 }
0203
0204 template<typename T>
0205 void destroy(T* p)
0206 {
0207 p->~T();
0208 }
0209
0210 template<typename T,typename U>
0211 void destroy(value_holder<T,U>* p)
0212 {
0213 traits::destroy(
0214 allocator(),
0215 reinterpret_cast<T*>(static_cast<value_holder_base<T>*>(p)));
0216 }
0217
0218 allocator_adaptor
0219 select_on_container_copy_construction()const noexcept
0220 {
0221 return traits::select_on_container_copy_construction(allocator());
0222 }
0223
0224 private:
0225 template<typename T,typename... Args>
0226 void construct_(
0227 std::integral_constant<int,0>,
0228 T* p,Args&&... args)
0229 {
0230 ::new ((void*)p) T(std::forward<Args>(args)...);
0231 }
0232
0233 template<typename T,typename... Args>
0234 void construct_(
0235 std::integral_constant<int,1>,
0236 T* p,Args&&... args)
0237 {
0238 ::new ((void*)p) T(std::allocator_arg,*this,std::forward<Args>(args)...);
0239 }
0240
0241 template<typename T,typename... Args>
0242 void construct_(
0243 std::integral_constant<int,2>,
0244 T* p,Args&&... args)
0245 {
0246 ::new ((void*)p) T(std::forward<Args>(args)...,*this);
0247 }
0248
0249 template<typename... Args,std::size_t... I>
0250 std::tuple<Args&&...> transform_tuple(
0251 std::integral_constant<int,0>,
0252 std::tuple<Args...>&& t,mp11::index_sequence<I...>)
0253 {
0254 return std::tuple<Args&&...>(std::get<I>(std::move(t))...);
0255 }
0256
0257 template<typename... Args,std::size_t... I>
0258 std::tuple<std::allocator_arg_t,allocator_adaptor&,Args&&...>
0259 transform_tuple(
0260 std::integral_constant<int,1>,
0261 std::tuple<Args...>&& t,mp11::index_sequence<I...>)
0262 {
0263 return std::tuple<
0264 std::allocator_arg_t,allocator_adaptor&,Args&&...>(
0265 std::allocator_arg,*this,std::get<I>(std::move(t))...);
0266 }
0267
0268 template<typename... Args,std::size_t... I>
0269 std::tuple<Args&&...,allocator_adaptor&>
0270 transform_tuple(
0271 std::integral_constant<int,2>,
0272 std::tuple<Args...>&& t,mp11::index_sequence<I...>)
0273 {
0274 return std::tuple<Args&&...,allocator_adaptor&>(
0275 std::get<I>(std::move(t))...,*this);
0276 }
0277 };
0278
0279 template<typename Allocator1,typename Allocator2>
0280 bool operator==(
0281 const allocator_adaptor<Allocator1>& x,
0282 const allocator_adaptor<Allocator2>& y)noexcept
0283 {
0284 return x.allocator()==y.allocator();
0285 }
0286
0287 template<typename Allocator1,typename Allocator2>
0288 bool operator!=(
0289 const allocator_adaptor<Allocator1>& x,
0290 const allocator_adaptor<Allocator2>& y)noexcept
0291 {
0292 return !(x==y);
0293 }
0294
0295 }
0296
0297 }
0298
0299 }
0300
0301 #endif