| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | #ifndef _SCOPED_ALLOCATOR |
| 30 | #define _SCOPED_ALLOCATOR 1 |
| 31 | |
| 32 | #pragma GCC system_header |
| 33 | |
| 34 | #if __cplusplus < 201103L |
| 35 | # include <bits/c++0x_warning.h> |
| 36 | #else |
| 37 | |
| 38 | #include <utility> |
| 39 | #include <tuple> |
| 40 | #include <bits/alloc_traits.h> |
| 41 | |
| 42 | namespace std _GLIBCXX_VISIBILITY(default) |
| 43 | { |
| 44 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | template<typename _Alloc> |
| 52 | using __outer_allocator_t |
| 53 | = decltype(std::declval<_Alloc>().outer_allocator()); |
| 54 | |
| 55 | template<typename _Alloc, typename = void> |
| 56 | struct __outermost_type |
| 57 | { |
| 58 | using type = _Alloc; |
| 59 | static type& _S_outermost(_Alloc& __a) { return __a; } |
| 60 | }; |
| 61 | |
| 62 | template<typename _Alloc> |
| 63 | struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> |
| 64 | : __outermost_type< |
| 65 | typename remove_reference<__outer_allocator_t<_Alloc>>::type |
| 66 | > |
| 67 | { |
| 68 | using __base = __outermost_type< |
| 69 | typename remove_reference<__outer_allocator_t<_Alloc>>::type |
| 70 | >; |
| 71 | |
| 72 | static typename __base::type& |
| 73 | _S_outermost(_Alloc& __a) |
| 74 | { return __base::_S_outermost(__a.outer_allocator()); } |
| 75 | }; |
| 76 | |
| 77 | template<typename _Alloc> |
| 78 | inline typename __outermost_type<_Alloc>::type& |
| 79 | __outermost(_Alloc& __a) |
| 80 | { return __outermost_type<_Alloc>::_S_outermost(__a); } |
| 81 | |
| 82 | template<typename _OuterAlloc, typename... _InnerAllocs> |
| 83 | class scoped_allocator_adaptor; |
| 84 | |
| 85 | template<typename...> |
| 86 | struct __inner_type_impl; |
| 87 | |
| 88 | template<typename _Outer> |
| 89 | struct __inner_type_impl<_Outer> |
| 90 | { |
| 91 | typedef scoped_allocator_adaptor<_Outer> __type; |
| 92 | |
| 93 | __inner_type_impl() = default; |
| 94 | __inner_type_impl(const __inner_type_impl&) = default; |
| 95 | __inner_type_impl(__inner_type_impl&&) = default; |
| 96 | __inner_type_impl& operator=(const __inner_type_impl&) = default; |
| 97 | __inner_type_impl& operator=(__inner_type_impl&&) = default; |
| 98 | |
| 99 | template<typename _Alloc> |
| 100 | __inner_type_impl(const __inner_type_impl<_Alloc>& __other) |
| 101 | { } |
| 102 | |
| 103 | template<typename _Alloc> |
| 104 | __inner_type_impl(__inner_type_impl<_Alloc>&& __other) |
| 105 | { } |
| 106 | |
| 107 | __type& |
| 108 | _M_get(__type* __p) noexcept { return *__p; } |
| 109 | |
| 110 | const __type& |
| 111 | _M_get(const __type* __p) const noexcept { return *__p; } |
| 112 | |
| 113 | tuple<> |
| 114 | _M_tie() const noexcept { return tuple<>(); } |
| 115 | |
| 116 | bool |
| 117 | operator==(const __inner_type_impl&) const noexcept |
| 118 | { return true; } |
| 119 | }; |
| 120 | |
| 121 | template<typename _Outer, typename _InnerHead, typename... _InnerTail> |
| 122 | struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> |
| 123 | { |
| 124 | typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; |
| 125 | |
| 126 | __inner_type_impl() = default; |
| 127 | __inner_type_impl(const __inner_type_impl&) = default; |
| 128 | __inner_type_impl(__inner_type_impl&&) = default; |
| 129 | __inner_type_impl& operator=(const __inner_type_impl&) = default; |
| 130 | __inner_type_impl& operator=(__inner_type_impl&&) = default; |
| 131 | |
| 132 | template<typename... _Allocs> |
| 133 | __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) |
| 134 | : _M_inner(__other._M_inner) { } |
| 135 | |
| 136 | template<typename... _Allocs> |
| 137 | __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) |
| 138 | : _M_inner(std::move(__other._M_inner)) { } |
| 139 | |
| 140 | template<typename... _Args> |
| 141 | explicit |
| 142 | __inner_type_impl(_Args&&... __args) |
| 143 | : _M_inner(std::forward<_Args>(__args)...) { } |
| 144 | |
| 145 | __type& |
| 146 | _M_get(void*) noexcept { return _M_inner; } |
| 147 | |
| 148 | const __type& |
| 149 | _M_get(const void*) const noexcept { return _M_inner; } |
| 150 | |
| 151 | tuple<const _InnerHead&, const _InnerTail&...> |
| 152 | _M_tie() const noexcept |
| 153 | { return _M_inner._M_tie(); } |
| 154 | |
| 155 | bool |
| 156 | operator==(const __inner_type_impl& __other) const noexcept |
| 157 | { return _M_inner == __other._M_inner; } |
| 158 | |
| 159 | private: |
| 160 | template<typename...> friend class __inner_type_impl; |
| 161 | template<typename, typename...> friend class scoped_allocator_adaptor; |
| 162 | |
| 163 | __type _M_inner; |
| 164 | }; |
| 165 | |
| 166 | |
| 167 | template<typename _OuterAlloc, typename... _InnerAllocs> |
| 168 | class scoped_allocator_adaptor |
| 169 | : public _OuterAlloc |
| 170 | { |
| 171 | typedef allocator_traits<_OuterAlloc> __traits; |
| 172 | |
| 173 | typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; |
| 174 | __inner_type _M_inner; |
| 175 | |
| 176 | template<typename _Outer, typename... _Inner> |
| 177 | friend class scoped_allocator_adaptor; |
| 178 | |
| 179 | template<typename...> |
| 180 | friend class __inner_type_impl; |
| 181 | |
| 182 | tuple<const _OuterAlloc&, const _InnerAllocs&...> |
| 183 | _M_tie() const noexcept |
| 184 | { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } |
| 185 | |
| 186 | template<typename _Alloc> |
| 187 | using __outermost_alloc_traits |
| 188 | = allocator_traits<typename __outermost_type<_Alloc>::type>; |
| 189 | |
| 190 | template<typename _Tp, typename... _Args> |
| 191 | void |
| 192 | _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) |
| 193 | { |
| 194 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
| 195 | _O_traits::construct(__outermost(*this), __p, |
| 196 | std::forward<_Args>(__args)...); |
| 197 | } |
| 198 | |
| 199 | typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_; |
| 200 | typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_; |
| 201 | |
| 202 | template<typename _Tp, typename... _Args> |
| 203 | void |
| 204 | _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) |
| 205 | { |
| 206 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
| 207 | _O_traits::construct(__outermost(*this), __p, |
| 208 | allocator_arg, inner_allocator(), |
| 209 | std::forward<_Args>(__args)...); |
| 210 | } |
| 211 | |
| 212 | template<typename _Tp, typename... _Args> |
| 213 | void |
| 214 | _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) |
| 215 | { |
| 216 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
| 217 | _O_traits::construct(__outermost(*this), __p, |
| 218 | std::forward<_Args>(__args)..., |
| 219 | inner_allocator()); |
| 220 | } |
| 221 | |
| 222 | template<typename _Alloc> |
| 223 | static _Alloc |
| 224 | _S_select_on_copy(const _Alloc& __a) |
| 225 | { |
| 226 | typedef allocator_traits<_Alloc> __a_traits; |
| 227 | return __a_traits::select_on_container_copy_construction(__a); |
| 228 | } |
| 229 | |
| 230 | template<std::size_t... _Indices> |
| 231 | scoped_allocator_adaptor(tuple<const _OuterAlloc&, |
| 232 | const _InnerAllocs&...> __refs, |
| 233 | _Index_tuple<_Indices...>) |
| 234 | : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), |
| 235 | _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) |
| 236 | { } |
| 237 | |
| 238 | |
| 239 | template<typename _Alloc> |
| 240 | using _Constructible = typename enable_if< |
| 241 | is_constructible<_OuterAlloc, _Alloc>::value |
| 242 | >::type; |
| 243 | |
| 244 | public: |
| 245 | typedef _OuterAlloc outer_allocator_type; |
| 246 | typedef typename __inner_type::__type inner_allocator_type; |
| 247 | |
| 248 | typedef typename __traits::value_type value_type; |
| 249 | typedef typename __traits::size_type size_type; |
| 250 | typedef typename __traits::difference_type difference_type; |
| 251 | typedef typename __traits::pointer pointer; |
| 252 | typedef typename __traits::const_pointer const_pointer; |
| 253 | typedef typename __traits::void_pointer void_pointer; |
| 254 | typedef typename __traits::const_void_pointer const_void_pointer; |
| 255 | |
| 256 | typedef typename __or_< |
| 257 | typename __traits::propagate_on_container_copy_assignment, |
| 258 | typename allocator_traits<_InnerAllocs>:: |
| 259 | propagate_on_container_copy_assignment...>::type |
| 260 | propagate_on_container_copy_assignment; |
| 261 | |
| 262 | typedef typename __or_< |
| 263 | typename __traits::propagate_on_container_move_assignment, |
| 264 | typename allocator_traits<_InnerAllocs>:: |
| 265 | propagate_on_container_move_assignment...>::type |
| 266 | propagate_on_container_move_assignment; |
| 267 | |
| 268 | typedef typename __or_< |
| 269 | typename __traits::propagate_on_container_swap, |
| 270 | typename allocator_traits<_InnerAllocs>:: |
| 271 | propagate_on_container_swap...>::type |
| 272 | propagate_on_container_swap; |
| 273 | |
| 274 | typedef typename __and_< |
| 275 | typename __traits::is_always_equal, |
| 276 | typename allocator_traits<_InnerAllocs>::is_always_equal...>::type |
| 277 | is_always_equal; |
| 278 | |
| 279 | template <class _Tp> |
| 280 | struct rebind |
| 281 | { |
| 282 | typedef scoped_allocator_adaptor< |
| 283 | typename __traits::template rebind_alloc<_Tp>, |
| 284 | _InnerAllocs...> other; |
| 285 | }; |
| 286 | |
| 287 | scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } |
| 288 | |
| 289 | template<typename _Outer2, typename = _Constructible<_Outer2>> |
| 290 | scoped_allocator_adaptor(_Outer2&& __outer, |
| 291 | const _InnerAllocs&... __inner) |
| 292 | : _OuterAlloc(std::forward<_Outer2>(__outer)), |
| 293 | _M_inner(__inner...) |
| 294 | { } |
| 295 | |
| 296 | scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) |
| 297 | : _OuterAlloc(__other.outer_allocator()), |
| 298 | _M_inner(__other._M_inner) |
| 299 | { } |
| 300 | |
| 301 | scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) |
| 302 | : _OuterAlloc(std::move(__other.outer_allocator())), |
| 303 | _M_inner(std::move(__other._M_inner)) |
| 304 | { } |
| 305 | |
| 306 | template<typename _Outer2, typename = _Constructible<const _Outer2&>> |
| 307 | scoped_allocator_adaptor( |
| 308 | const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) |
| 309 | : _OuterAlloc(__other.outer_allocator()), |
| 310 | _M_inner(__other._M_inner) |
| 311 | { } |
| 312 | |
| 313 | template<typename _Outer2, typename = _Constructible<_Outer2>> |
| 314 | scoped_allocator_adaptor( |
| 315 | scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) |
| 316 | : _OuterAlloc(std::move(__other.outer_allocator())), |
| 317 | _M_inner(std::move(__other._M_inner)) |
| 318 | { } |
| 319 | |
| 320 | scoped_allocator_adaptor& |
| 321 | operator=(const scoped_allocator_adaptor&) = default; |
| 322 | |
| 323 | scoped_allocator_adaptor& |
| 324 | operator=(scoped_allocator_adaptor&&) = default; |
| 325 | |
| 326 | inner_allocator_type& inner_allocator() noexcept |
| 327 | { return _M_inner._M_get(this); } |
| 328 | |
| 329 | const inner_allocator_type& inner_allocator() const noexcept |
| 330 | { return _M_inner._M_get(this); } |
| 331 | |
| 332 | outer_allocator_type& outer_allocator() noexcept |
| 333 | { return static_cast<_OuterAlloc&>(*this); } |
| 334 | |
| 335 | const outer_allocator_type& outer_allocator() const noexcept |
| 336 | { return static_cast<const _OuterAlloc&>(*this); } |
| 337 | |
| 338 | pointer allocate(size_type __n) |
| 339 | { return __traits::allocate(outer_allocator(), __n); } |
| 340 | |
| 341 | pointer allocate(size_type __n, const_void_pointer __hint) |
| 342 | { return __traits::allocate(outer_allocator(), __n, __hint); } |
| 343 | |
| 344 | void deallocate(pointer __p, size_type __n) |
| 345 | { return __traits::deallocate(outer_allocator(), __p, __n); } |
| 346 | |
| 347 | size_type max_size() const |
| 348 | { return __traits::max_size(outer_allocator()); } |
| 349 | |
| 350 | template<typename _Tp, typename... _Args> |
| 351 | void construct(_Tp* __p, _Args&&... __args) |
| 352 | { |
| 353 | auto& __inner = inner_allocator(); |
| 354 | auto __use_tag |
| 355 | = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); |
| 356 | _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); |
| 357 | } |
| 358 | |
| 359 | template<typename _T1, typename _T2, typename... _Args1, |
| 360 | typename... _Args2> |
| 361 | void |
| 362 | construct(pair<_T1, _T2>* __p, piecewise_construct_t, |
| 363 | tuple<_Args1...> __x, tuple<_Args2...> __y) |
| 364 | { |
| 365 | |
| 366 | |
| 367 | auto& __inner = inner_allocator(); |
| 368 | auto __x_use_tag |
| 369 | = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); |
| 370 | auto __y_use_tag |
| 371 | = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); |
| 372 | typename _Build_index_tuple<sizeof...(_Args1)>::__type __x_indices; |
| 373 | typename _Build_index_tuple<sizeof...(_Args2)>::__type __y_indices; |
| 374 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
| 375 | _O_traits::construct(__outermost(*this), __p, piecewise_construct, |
| 376 | _M_construct_p(__x_use_tag, __x_indices, __x), |
| 377 | _M_construct_p(__y_use_tag, __y_indices, __y)); |
| 378 | } |
| 379 | |
| 380 | template<typename _T1, typename _T2> |
| 381 | void |
| 382 | construct(pair<_T1, _T2>* __p) |
| 383 | { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } |
| 384 | |
| 385 | template<typename _T1, typename _T2, typename _Up, typename _Vp> |
| 386 | void |
| 387 | construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) |
| 388 | { |
| 389 | construct(__p, piecewise_construct, |
| 390 | std::forward_as_tuple(std::forward<_Up>(__u)), |
| 391 | std::forward_as_tuple(std::forward<_Vp>(__v))); |
| 392 | } |
| 393 | |
| 394 | template<typename _T1, typename _T2, typename _Up, typename _Vp> |
| 395 | void |
| 396 | construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) |
| 397 | { |
| 398 | construct(__p, piecewise_construct, |
| 399 | std::forward_as_tuple(__x.first), |
| 400 | std::forward_as_tuple(__x.second)); |
| 401 | } |
| 402 | |
| 403 | template<typename _T1, typename _T2, typename _Up, typename _Vp> |
| 404 | void |
| 405 | construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) |
| 406 | { |
| 407 | construct(__p, piecewise_construct, |
| 408 | std::forward_as_tuple(std::forward<_Up>(__x.first)), |
| 409 | std::forward_as_tuple(std::forward<_Vp>(__x.second))); |
| 410 | } |
| 411 | |
| 412 | template<typename _Tp> |
| 413 | void destroy(_Tp* __p) |
| 414 | { |
| 415 | typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; |
| 416 | _O_traits::destroy(__outermost(*this), __p); |
| 417 | } |
| 418 | |
| 419 | scoped_allocator_adaptor |
| 420 | select_on_container_copy_construction() const |
| 421 | { |
| 422 | typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type |
| 423 | _Indices; |
| 424 | return scoped_allocator_adaptor(_M_tie(), _Indices()); |
| 425 | } |
| 426 | |
| 427 | template <typename _OutA1, typename _OutA2, typename... _InA> |
| 428 | friend bool |
| 429 | operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, |
| 430 | const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; |
| 431 | |
| 432 | private: |
| 433 | template<typename _Ind, typename... _Args> |
| 434 | tuple<_Args&&...> |
| 435 | _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) |
| 436 | { return std::move(__t); } |
| 437 | |
| 438 | template<size_t... _Ind, typename... _Args> |
| 439 | tuple<allocator_arg_t, inner_allocator_type&, _Args&&...> |
| 440 | _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, |
| 441 | tuple<_Args...>& __t) |
| 442 | { |
| 443 | return { allocator_arg, inner_allocator(), |
| 444 | std::get<_Ind>(std::move(__t))... |
| 445 | }; |
| 446 | } |
| 447 | |
| 448 | template<size_t... _Ind, typename... _Args> |
| 449 | tuple<_Args&&..., inner_allocator_type&> |
| 450 | _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, |
| 451 | tuple<_Args...>& __t) |
| 452 | { |
| 453 | return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; |
| 454 | } |
| 455 | }; |
| 456 | |
| 457 | template <typename _OutA1, typename _OutA2, typename... _InA> |
| 458 | inline bool |
| 459 | operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, |
| 460 | const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept |
| 461 | { |
| 462 | return __a.outer_allocator() == __b.outer_allocator() |
| 463 | && __a._M_inner == __b._M_inner; |
| 464 | } |
| 465 | |
| 466 | template <typename _OutA1, typename _OutA2, typename... _InA> |
| 467 | inline bool |
| 468 | operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, |
| 469 | const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept |
| 470 | { return !(__a == __b); } |
| 471 | |
| 472 | |
| 473 | |
| 474 | _GLIBCXX_END_NAMESPACE_VERSION |
| 475 | } |
| 476 | |
| 477 | #endif |
| 478 | |
| 479 | #endif |
| 480 | |