1// <scoped_allocator> -*- C++ -*- 2 3// Copyright (C) 2011-2014 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 78 template<typename _Alloc> 79 inline auto 80 __do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator()) 81 { return __a.outer_allocator(); } 82 83 template<typename _Alloc> 84 inline _Alloc& 85 __do_outermost(_Alloc& __a, ...) 86 { return __a; } 87 88 // TODO: make recursive (see note in 20.12.4/1) 89 template<typename _Alloc> 90 inline auto 91 __outermost(_Alloc& __a) -> decltype(__do_outermost(__a, &__a)) 92 { return __do_outermost(__a, &__a); } 93 94 template<typename _OuterAlloc, typename... _InnerAllocs> 95 class scoped_allocator_adaptor; 96 97 template<typename...> 98 struct __inner_type_impl; 99 100 template<typename _Outer> 101 struct __inner_type_impl<_Outer> 102 { 103 typedef scoped_allocator_adaptor<_Outer> __type; 104 105 __inner_type_impl() = default; 106 __inner_type_impl(const __inner_type_impl&) = default; 107 __inner_type_impl(__inner_type_impl&&) = default; 108 __inner_type_impl& operator=(const __inner_type_impl&) = default; 109 __inner_type_impl& operator=(__inner_type_impl&&) = default; 110 111 template<typename _Alloc> 112 __inner_type_impl(const __inner_type_impl<_Alloc>& __other) 113 { } 114 115 template<typename _Alloc> 116 __inner_type_impl(__inner_type_impl<_Alloc>&& __other) 117 { } 118 119 __type& 120 _M_get(__type* __p) noexcept { return *__p; } 121 122 const __type& 123 _M_get(const __type* __p) const noexcept { return *__p; } 124 125 tuple<> 126 _M_tie() const noexcept { return tuple<>(); } 127 128 bool 129 operator==(const __inner_type_impl&) const noexcept 130 { return true; } 131 }; 132 133 template<typename _Outer, typename _InnerHead, typename... _InnerTail> 134 struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> 135 { 136 typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; 137 138 __inner_type_impl() = default; 139 __inner_type_impl(const __inner_type_impl&) = default; 140 __inner_type_impl(__inner_type_impl&&) = default; 141 __inner_type_impl& operator=(const __inner_type_impl&) = default; 142 __inner_type_impl& operator=(__inner_type_impl&&) = default; 143 144 template<typename... _Allocs> 145 __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) 146 : _M_inner(__other._M_inner) { } 147 148 template<typename... _Allocs> 149 __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) 150 : _M_inner(std::move(__other._M_inner)) { } 151 152 template<typename... _Args> 153 explicit 154 __inner_type_impl(_Args&&... __args) 155 : _M_inner(std::forward<_Args>(__args)...) { } 156 157 __type& 158 _M_get(void*) noexcept { return _M_inner; } 159 160 const __type& 161 _M_get(const void*) const noexcept { return _M_inner; } 162 163 tuple<const _InnerHead&, const _InnerTail&...> 164 _M_tie() const noexcept 165 { return _M_inner._M_tie(); } 166 167 bool 168 operator==(const __inner_type_impl& __other) const noexcept 169 { return _M_inner == __other._M_inner; } 170 171 private: 172 template<typename...> friend class __inner_type_impl; 173 template<typename, typename...> friend class scoped_allocator_adaptor; 174 175 __type _M_inner; 176 }; 177 178 /// Primary class template. 179 template<typename _OuterAlloc, typename... _InnerAllocs> 180 class scoped_allocator_adaptor 181 : public _OuterAlloc 182 { 183 typedef allocator_traits<_OuterAlloc> __traits; 184 185 typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; 186 __inner_type _M_inner; 187 188 template<typename _Outer, typename... _Inner> 189 friend class scoped_allocator_adaptor; 190 191 template<typename...> 192 friend class __inner_type_impl; 193 194 tuple<const _OuterAlloc&, const _InnerAllocs&...> 195 _M_tie() const noexcept 196 { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } 197 198 template<typename _Alloc> 199 using __outermost_type = typename 200 std::decay<decltype(__outermost(std::declval<_Alloc&>()))>::type; 201 202 template<typename _Alloc> 203 using __outermost_alloc_traits 204 = allocator_traits<__outermost_type<_Alloc>>; 205 206 template<typename _Tp, typename... _Args> 207 void 208 _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) 209 { 210 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 211 _O_traits::construct(__outermost(*this), __p, 212 std::forward<_Args>(__args)...); 213 } 214 215 typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_; 216 typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_; 217 218 template<typename _Tp, typename... _Args> 219 void 220 _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) 221 { 222 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 223 _O_traits::construct(__outermost(*this), __p, 224 allocator_arg, inner_allocator(), 225 std::forward<_Args>(__args)...); 226 } 227 228 template<typename _Tp, typename... _Args> 229 void 230 _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) 231 { 232 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 233 _O_traits::construct(__outermost(*this), __p, 234 std::forward<_Args>(__args)..., 235 inner_allocator()); 236 } 237 238 template<typename _Alloc> 239 static _Alloc 240 _S_select_on_copy(const _Alloc& __a) 241 { 242 typedef allocator_traits<_Alloc> __a_traits; 243 return __a_traits::select_on_container_copy_construction(__a); 244 } 245 246 template<std::size_t... _Indices> 247 scoped_allocator_adaptor(tuple<const _OuterAlloc&, 248 const _InnerAllocs&...> __refs, 249 _Index_tuple<_Indices...>) 250 : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), 251 _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) 252 { } 253 254 public: 255 typedef _OuterAlloc outer_allocator_type; 256 typedef typename __inner_type::__type inner_allocator_type; 257 258 typedef typename __traits::value_type value_type; 259 typedef typename __traits::size_type size_type; 260 typedef typename __traits::difference_type difference_type; 261 typedef typename __traits::pointer pointer; 262 typedef typename __traits::const_pointer const_pointer; 263 typedef typename __traits::void_pointer void_pointer; 264 typedef typename __traits::const_void_pointer const_void_pointer; 265 266 typedef typename conditional< 267 __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value, 268 true_type, false_type>::type propagate_on_container_copy_assignment; 269 typedef typename conditional< 270 __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value, 271 true_type, false_type>::type propagate_on_container_move_assignment; 272 typedef typename conditional< 273 __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value, 274 true_type, false_type>::type propagate_on_container_swap; 275 276 template <class _Tp> 277 struct rebind 278 { 279 typedef scoped_allocator_adaptor< 280 typename __traits::template rebind_alloc<_Tp>, 281 _InnerAllocs...> other; 282 }; 283 284 scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } 285 286 template<typename _Outer2> 287 scoped_allocator_adaptor(_Outer2&& __outer, 288 const _InnerAllocs&... __inner) 289 : _OuterAlloc(std::forward<_Outer2>(__outer)), 290 _M_inner(__inner...) 291 { } 292 293 scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) 294 : _OuterAlloc(__other.outer_allocator()), 295 _M_inner(__other._M_inner) 296 { } 297 298 scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) 299 : _OuterAlloc(std::move(__other.outer_allocator())), 300 _M_inner(std::move(__other._M_inner)) 301 { } 302 303 template<typename _Outer2> 304 scoped_allocator_adaptor( 305 const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) 306 : _OuterAlloc(__other.outer_allocator()), 307 _M_inner(__other._M_inner) 308 { } 309 310 template<typename _Outer2> 311 scoped_allocator_adaptor( 312 scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) 313 : _OuterAlloc(std::move(__other.outer_allocator())), 314 _M_inner(std::move(__other._M_inner)) 315 { } 316 317 scoped_allocator_adaptor& 318 operator=(const scoped_allocator_adaptor&) = default; 319 320 scoped_allocator_adaptor& 321 operator=(scoped_allocator_adaptor&&) = default; 322 323 inner_allocator_type& inner_allocator() noexcept 324 { return _M_inner._M_get(this); } 325 326 const inner_allocator_type& inner_allocator() const noexcept 327 { return _M_inner._M_get(this); } 328 329 outer_allocator_type& outer_allocator() noexcept 330 { return static_cast<_OuterAlloc&>(*this); } 331 332 const outer_allocator_type& outer_allocator() const noexcept 333 { return static_cast<const _OuterAlloc&>(*this); } 334 335 pointer allocate(size_type __n) 336 { return __traits::allocate(outer_allocator(), __n); } 337 338 pointer allocate(size_type __n, const_void_pointer __hint) 339 { return __traits::allocate(outer_allocator(), __n, __hint); } 340 341 void deallocate(pointer __p, size_type __n) 342 { return __traits::deallocate(outer_allocator(), __p, __n); } 343 344 size_type max_size() const 345 { return __traits::max_size(outer_allocator()); } 346 347 template<typename _Tp, typename... _Args> 348 void construct(_Tp* __p, _Args&&... __args) 349 { 350 auto& __inner = inner_allocator(); 351 auto __use_tag 352 = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); 353 _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); 354 } 355 356 template<typename _T1, typename _T2, typename... _Args1, 357 typename... _Args2> 358 void 359 construct(pair<_T1, _T2>* __p, piecewise_construct_t, 360 tuple<_Args1...> __x, tuple<_Args2...> __y) 361 { 362 // _GLIBCXX_RESOLVE_LIB_DEFECTS 363 // 2203. wrong argument types for piecewise construction 364 auto& __inner = inner_allocator(); 365 auto __x_use_tag 366 = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); 367 auto __y_use_tag 368 = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); 369 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 370 _O_traits::construct(__outermost(*this), __p, piecewise_construct, 371 _M_construct_p(__x_use_tag, __x), 372 _M_construct_p(__y_use_tag, __y)); 373 } 374 375 template<typename _T1, typename _T2> 376 void 377 construct(pair<_T1, _T2>* __p) 378 { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } 379 380 template<typename _T1, typename _T2, typename _Up, typename _Vp> 381 void 382 construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) 383 { 384 construct(__p, piecewise_construct, 385 std::forward_as_tuple(std::forward<_Up>(__u)), 386 std::forward_as_tuple(std::forward<_Vp>(__v))); 387 } 388 389 template<typename _T1, typename _T2, typename _Up, typename _Vp> 390 void 391 construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) 392 { 393 construct(__p, piecewise_construct, 394 std::forward_as_tuple(__x.first), 395 std::forward_as_tuple(__x.second)); 396 } 397 398 template<typename _T1, typename _T2, typename _Up, typename _Vp> 399 void 400 construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) 401 { 402 construct(__p, piecewise_construct, 403 std::forward_as_tuple(std::forward<_Up>(__x.first)), 404 std::forward_as_tuple(std::forward<_Vp>(__x.second))); 405 } 406 407 template<typename _Tp> 408 void destroy(_Tp* __p) 409 { 410 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 411 _O_traits::destroy(__outermost(*this), __p); 412 } 413 414 scoped_allocator_adaptor 415 select_on_container_copy_construction() const 416 { 417 typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type 418 _Indices; 419 return scoped_allocator_adaptor(_M_tie(), _Indices()); 420 } 421 422 template <typename _OutA1, typename _OutA2, typename... _InA> 423 friend bool 424 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 425 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; 426 427 private: 428 template<typename _Tuple> 429 _Tuple&& 430 _M_construct_p(__uses_alloc0, _Tuple& __t) 431 { return std::move(__t); } 432 433 template<typename... _Args> 434 std::tuple<allocator_arg_t, inner_allocator_type&, _Args...> 435 _M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t) 436 { 437 typedef std::tuple<allocator_arg_t, inner_allocator_type&> _Tuple; 438 return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()), 439 std::move(__t)); 440 } 441 442 template<typename... _Args> 443 std::tuple<_Args..., inner_allocator_type&> 444 _M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t) 445 { 446 typedef std::tuple<inner_allocator_type&> _Tuple; 447 return std::tuple_cat(std::move(__t), _Tuple(inner_allocator())); 448 } 449 }; 450 451 template <typename _OutA1, typename _OutA2, typename... _InA> 452 inline bool 453 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 454 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 455 { 456 return __a.outer_allocator() == __b.outer_allocator() 457 && __a._M_inner == __b._M_inner; 458 } 459 460 template <typename _OutA1, typename _OutA2, typename... _InA> 461 inline bool 462 operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 463 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 464 { return !(__a == __b); } 465 466 /// @} 467 468_GLIBCXX_END_NAMESPACE_VERSION 469} // namespace 470 471#endif // C++11 472 473#endif // _SCOPED_ALLOCATOR 474