1// <scoped_allocator> -*- C++ -*- 2 3// Copyright (C) 2011-2015 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file include/scoped_allocator 26 * This is a Standard C++ Library header. 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 42namespace std _GLIBCXX_VISIBILITY(default) 43{ 44_GLIBCXX_BEGIN_NAMESPACE_VERSION 45 46 template<template<typename> class _Pred, typename... _Allocs> 47 struct __any_of; 48 49 template<template<typename> class _Pred, typename _Alloc, typename... _Allocs> 50 struct __any_of<_Pred, _Alloc, _Allocs...> 51 : __or_<_Pred<_Alloc>, __any_of<_Pred, _Allocs...>> 52 { }; 53 54 template<template<typename> class _Pred, typename _Alloc> 55 struct __any_of<_Pred, _Alloc> 56 : _Pred<_Alloc> 57 { }; 58 59 /** 60 * @addtogroup allocators 61 * @{ 62 */ 63 64 template<typename _Alloc> 65 struct __propagate_on_copy 66 : allocator_traits<_Alloc>::propagate_on_container_copy_assignment 67 { }; 68 template<typename _Alloc> 69 struct __propagate_on_move 70 : allocator_traits<_Alloc>::propagate_on_container_move_assignment 71 { }; 72 template<typename _Alloc> 73 struct __propagate_on_swap 74 : allocator_traits<_Alloc>::propagate_on_container_swap 75 { }; 76 77 template<typename _Alloc> 78 using __outer_allocator_t 79 = decltype(std::declval<_Alloc>().outer_allocator()); 80 81 template<typename _Alloc, typename = void> 82 struct __outermost_type 83 { 84 using type = _Alloc; 85 static type& _S_outermost(_Alloc& __a) { return __a; } 86 }; 87 88 template<typename _Alloc> 89 struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> 90 : __outermost_type< 91 typename remove_reference<__outer_allocator_t<_Alloc>>::type 92 > 93 { 94 using __base = __outermost_type< 95 typename remove_reference<__outer_allocator_t<_Alloc>>::type 96 >; 97 98 static typename __base::type& 99 _S_outermost(_Alloc& __a) 100 { return __base::_S_outermost(__a.outer_allocator()); } 101 }; 102 103 template<typename _Alloc> 104 inline typename __outermost_type<_Alloc>::type& 105 __outermost(_Alloc& __a) 106 { return __outermost_type<_Alloc>::_S_outermost(__a); } 107 108 template<typename _OuterAlloc, typename... _InnerAllocs> 109 class scoped_allocator_adaptor; 110 111 template<typename...> 112 struct __inner_type_impl; 113 114 template<typename _Outer> 115 struct __inner_type_impl<_Outer> 116 { 117 typedef scoped_allocator_adaptor<_Outer> __type; 118 119 __inner_type_impl() = default; 120 __inner_type_impl(const __inner_type_impl&) = default; 121 __inner_type_impl(__inner_type_impl&&) = default; 122 __inner_type_impl& operator=(const __inner_type_impl&) = default; 123 __inner_type_impl& operator=(__inner_type_impl&&) = default; 124 125 template<typename _Alloc> 126 __inner_type_impl(const __inner_type_impl<_Alloc>& __other) 127 { } 128 129 template<typename _Alloc> 130 __inner_type_impl(__inner_type_impl<_Alloc>&& __other) 131 { } 132 133 __type& 134 _M_get(__type* __p) noexcept { return *__p; } 135 136 const __type& 137 _M_get(const __type* __p) const noexcept { return *__p; } 138 139 tuple<> 140 _M_tie() const noexcept { return tuple<>(); } 141 142 bool 143 operator==(const __inner_type_impl&) const noexcept 144 { return true; } 145 }; 146 147 template<typename _Outer, typename _InnerHead, typename... _InnerTail> 148 struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> 149 { 150 typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; 151 152 __inner_type_impl() = default; 153 __inner_type_impl(const __inner_type_impl&) = default; 154 __inner_type_impl(__inner_type_impl&&) = default; 155 __inner_type_impl& operator=(const __inner_type_impl&) = default; 156 __inner_type_impl& operator=(__inner_type_impl&&) = default; 157 158 template<typename... _Allocs> 159 __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) 160 : _M_inner(__other._M_inner) { } 161 162 template<typename... _Allocs> 163 __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) 164 : _M_inner(std::move(__other._M_inner)) { } 165 166 template<typename... _Args> 167 explicit 168 __inner_type_impl(_Args&&... __args) 169 : _M_inner(std::forward<_Args>(__args)...) { } 170 171 __type& 172 _M_get(void*) noexcept { return _M_inner; } 173 174 const __type& 175 _M_get(const void*) const noexcept { return _M_inner; } 176 177 tuple<const _InnerHead&, const _InnerTail&...> 178 _M_tie() const noexcept 179 { return _M_inner._M_tie(); } 180 181 bool 182 operator==(const __inner_type_impl& __other) const noexcept 183 { return _M_inner == __other._M_inner; } 184 185 private: 186 template<typename...> friend class __inner_type_impl; 187 template<typename, typename...> friend class scoped_allocator_adaptor; 188 189 __type _M_inner; 190 }; 191 192 /// Primary class template. 193 template<typename _OuterAlloc, typename... _InnerAllocs> 194 class scoped_allocator_adaptor 195 : public _OuterAlloc 196 { 197 typedef allocator_traits<_OuterAlloc> __traits; 198 199 typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; 200 __inner_type _M_inner; 201 202 template<typename _Outer, typename... _Inner> 203 friend class scoped_allocator_adaptor; 204 205 template<typename...> 206 friend class __inner_type_impl; 207 208 tuple<const _OuterAlloc&, const _InnerAllocs&...> 209 _M_tie() const noexcept 210 { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } 211 212 template<typename _Alloc> 213 using __outermost_alloc_traits 214 = allocator_traits<typename __outermost_type<_Alloc>::type>; 215 216 template<typename _Tp, typename... _Args> 217 void 218 _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) 219 { 220 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 221 _O_traits::construct(__outermost(*this), __p, 222 std::forward<_Args>(__args)...); 223 } 224 225 typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_; 226 typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_; 227 228 template<typename _Tp, typename... _Args> 229 void 230 _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) 231 { 232 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 233 _O_traits::construct(__outermost(*this), __p, 234 allocator_arg, inner_allocator(), 235 std::forward<_Args>(__args)...); 236 } 237 238 template<typename _Tp, typename... _Args> 239 void 240 _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) 241 { 242 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 243 _O_traits::construct(__outermost(*this), __p, 244 std::forward<_Args>(__args)..., 245 inner_allocator()); 246 } 247 248 template<typename _Alloc> 249 static _Alloc 250 _S_select_on_copy(const _Alloc& __a) 251 { 252 typedef allocator_traits<_Alloc> __a_traits; 253 return __a_traits::select_on_container_copy_construction(__a); 254 } 255 256 template<std::size_t... _Indices> 257 scoped_allocator_adaptor(tuple<const _OuterAlloc&, 258 const _InnerAllocs&...> __refs, 259 _Index_tuple<_Indices...>) 260 : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), 261 _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) 262 { } 263 264 // Used to constrain constructors to disallow invalid conversions. 265 template<typename _Alloc> 266 using _Constructible = typename enable_if< 267 is_constructible<_OuterAlloc, _Alloc>::value 268 >::type; 269 270 public: 271 typedef _OuterAlloc outer_allocator_type; 272 typedef typename __inner_type::__type inner_allocator_type; 273 274 typedef typename __traits::value_type value_type; 275 typedef typename __traits::size_type size_type; 276 typedef typename __traits::difference_type difference_type; 277 typedef typename __traits::pointer pointer; 278 typedef typename __traits::const_pointer const_pointer; 279 typedef typename __traits::void_pointer void_pointer; 280 typedef typename __traits::const_void_pointer const_void_pointer; 281 282 typedef typename conditional< 283 __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value, 284 true_type, false_type>::type propagate_on_container_copy_assignment; 285 typedef typename conditional< 286 __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value, 287 true_type, false_type>::type propagate_on_container_move_assignment; 288 typedef typename conditional< 289 __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value, 290 true_type, false_type>::type propagate_on_container_swap; 291 292 template <class _Tp> 293 struct rebind 294 { 295 typedef scoped_allocator_adaptor< 296 typename __traits::template rebind_alloc<_Tp>, 297 _InnerAllocs...> other; 298 }; 299 300 scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } 301 302 template<typename _Outer2, typename = _Constructible<_Outer2>> 303 scoped_allocator_adaptor(_Outer2&& __outer, 304 const _InnerAllocs&... __inner) 305 : _OuterAlloc(std::forward<_Outer2>(__outer)), 306 _M_inner(__inner...) 307 { } 308 309 scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) 310 : _OuterAlloc(__other.outer_allocator()), 311 _M_inner(__other._M_inner) 312 { } 313 314 scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) 315 : _OuterAlloc(std::move(__other.outer_allocator())), 316 _M_inner(std::move(__other._M_inner)) 317 { } 318 319 template<typename _Outer2, typename = _Constructible<const _Outer2&>> 320 scoped_allocator_adaptor( 321 const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) 322 : _OuterAlloc(__other.outer_allocator()), 323 _M_inner(__other._M_inner) 324 { } 325 326 template<typename _Outer2, typename = _Constructible<_Outer2>> 327 scoped_allocator_adaptor( 328 scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) 329 : _OuterAlloc(std::move(__other.outer_allocator())), 330 _M_inner(std::move(__other._M_inner)) 331 { } 332 333 scoped_allocator_adaptor& 334 operator=(const scoped_allocator_adaptor&) = default; 335 336 scoped_allocator_adaptor& 337 operator=(scoped_allocator_adaptor&&) = default; 338 339 inner_allocator_type& inner_allocator() noexcept 340 { return _M_inner._M_get(this); } 341 342 const inner_allocator_type& inner_allocator() const noexcept 343 { return _M_inner._M_get(this); } 344 345 outer_allocator_type& outer_allocator() noexcept 346 { return static_cast<_OuterAlloc&>(*this); } 347 348 const outer_allocator_type& outer_allocator() const noexcept 349 { return static_cast<const _OuterAlloc&>(*this); } 350 351 pointer allocate(size_type __n) 352 { return __traits::allocate(outer_allocator(), __n); } 353 354 pointer allocate(size_type __n, const_void_pointer __hint) 355 { return __traits::allocate(outer_allocator(), __n, __hint); } 356 357 void deallocate(pointer __p, size_type __n) 358 { return __traits::deallocate(outer_allocator(), __p, __n); } 359 360 size_type max_size() const 361 { return __traits::max_size(outer_allocator()); } 362 363 template<typename _Tp, typename... _Args> 364 void construct(_Tp* __p, _Args&&... __args) 365 { 366 auto& __inner = inner_allocator(); 367 auto __use_tag 368 = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); 369 _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); 370 } 371 372 template<typename _T1, typename _T2, typename... _Args1, 373 typename... _Args2> 374 void 375 construct(pair<_T1, _T2>* __p, piecewise_construct_t, 376 tuple<_Args1...> __x, tuple<_Args2...> __y) 377 { 378 // _GLIBCXX_RESOLVE_LIB_DEFECTS 379 // 2203. wrong argument types for piecewise construction 380 auto& __inner = inner_allocator(); 381 auto __x_use_tag 382 = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); 383 auto __y_use_tag 384 = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); 385 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 386 _O_traits::construct(__outermost(*this), __p, piecewise_construct, 387 _M_construct_p(__x_use_tag, __x), 388 _M_construct_p(__y_use_tag, __y)); 389 } 390 391 template<typename _T1, typename _T2> 392 void 393 construct(pair<_T1, _T2>* __p) 394 { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } 395 396 template<typename _T1, typename _T2, typename _Up, typename _Vp> 397 void 398 construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) 399 { 400 construct(__p, piecewise_construct, 401 std::forward_as_tuple(std::forward<_Up>(__u)), 402 std::forward_as_tuple(std::forward<_Vp>(__v))); 403 } 404 405 template<typename _T1, typename _T2, typename _Up, typename _Vp> 406 void 407 construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) 408 { 409 construct(__p, piecewise_construct, 410 std::forward_as_tuple(__x.first), 411 std::forward_as_tuple(__x.second)); 412 } 413 414 template<typename _T1, typename _T2, typename _Up, typename _Vp> 415 void 416 construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) 417 { 418 construct(__p, piecewise_construct, 419 std::forward_as_tuple(std::forward<_Up>(__x.first)), 420 std::forward_as_tuple(std::forward<_Vp>(__x.second))); 421 } 422 423 template<typename _Tp> 424 void destroy(_Tp* __p) 425 { 426 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 427 _O_traits::destroy(__outermost(*this), __p); 428 } 429 430 scoped_allocator_adaptor 431 select_on_container_copy_construction() const 432 { 433 typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type 434 _Indices; 435 return scoped_allocator_adaptor(_M_tie(), _Indices()); 436 } 437 438 template <typename _OutA1, typename _OutA2, typename... _InA> 439 friend bool 440 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 441 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; 442 443 private: 444 template<typename _Tuple> 445 _Tuple&& 446 _M_construct_p(__uses_alloc0, _Tuple& __t) 447 { return std::move(__t); } 448 449 template<typename... _Args> 450 std::tuple<allocator_arg_t, inner_allocator_type&, _Args...> 451 _M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t) 452 { 453 typedef std::tuple<allocator_arg_t, inner_allocator_type&> _Tuple; 454 return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()), 455 std::move(__t)); 456 } 457 458 template<typename... _Args> 459 std::tuple<_Args..., inner_allocator_type&> 460 _M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t) 461 { 462 typedef std::tuple<inner_allocator_type&> _Tuple; 463 return std::tuple_cat(std::move(__t), _Tuple(inner_allocator())); 464 } 465 }; 466 467 template <typename _OutA1, typename _OutA2, typename... _InA> 468 inline bool 469 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 470 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 471 { 472 return __a.outer_allocator() == __b.outer_allocator() 473 && __a._M_inner == __b._M_inner; 474 } 475 476 template <typename _OutA1, typename _OutA2, typename... _InA> 477 inline bool 478 operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 479 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 480 { return !(__a == __b); } 481 482 /// @} 483 484_GLIBCXX_END_NAMESPACE_VERSION 485} // namespace 486 487#endif // C++11 488 489#endif // _SCOPED_ALLOCATOR 490