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