|
libstdc++
|
00001 // <scoped_allocator> -*- C++ -*- 00002 00003 // Copyright (C) 2011-2015 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file include/scoped_allocator 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 #ifndef _SCOPED_ALLOCATOR 00030 #define _SCOPED_ALLOCATOR 1 00031 00032 #pragma GCC system_header 00033 00034 #if __cplusplus < 201103L 00035 # include <bits/c++0x_warning.h> 00036 #else 00037 00038 #include <utility> 00039 #include <tuple> 00040 #include <bits/alloc_traits.h> 00041 00042 namespace std _GLIBCXX_VISIBILITY(default) 00043 { 00044 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00045 00046 template<template<typename> class _Pred, typename... _Allocs> 00047 struct __any_of; 00048 00049 template<template<typename> class _Pred, typename _Alloc, typename... _Allocs> 00050 struct __any_of<_Pred, _Alloc, _Allocs...> 00051 : __or_<_Pred<_Alloc>, __any_of<_Pred, _Allocs...>> 00052 { }; 00053 00054 template<template<typename> class _Pred, typename _Alloc> 00055 struct __any_of<_Pred, _Alloc> 00056 : _Pred<_Alloc> 00057 { }; 00058 00059 /** 00060 * @addtogroup allocators 00061 * @{ 00062 */ 00063 00064 template<typename _Alloc> 00065 struct __propagate_on_copy 00066 : allocator_traits<_Alloc>::propagate_on_container_copy_assignment 00067 { }; 00068 template<typename _Alloc> 00069 struct __propagate_on_move 00070 : allocator_traits<_Alloc>::propagate_on_container_move_assignment 00071 { }; 00072 template<typename _Alloc> 00073 struct __propagate_on_swap 00074 : allocator_traits<_Alloc>::propagate_on_container_swap 00075 { }; 00076 00077 template<typename _Alloc> 00078 using __outer_allocator_t 00079 = decltype(std::declval<_Alloc>().outer_allocator()); 00080 00081 template<typename _Alloc, typename = void> 00082 struct __outermost_type 00083 { 00084 using type = _Alloc; 00085 static type& _S_outermost(_Alloc& __a) { return __a; } 00086 }; 00087 00088 template<typename _Alloc> 00089 struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> 00090 : __outermost_type< 00091 typename remove_reference<__outer_allocator_t<_Alloc>>::type 00092 > 00093 { 00094 using __base = __outermost_type< 00095 typename remove_reference<__outer_allocator_t<_Alloc>>::type 00096 >; 00097 00098 static typename __base::type& 00099 _S_outermost(_Alloc& __a) 00100 { return __base::_S_outermost(__a.outer_allocator()); } 00101 }; 00102 00103 template<typename _Alloc> 00104 inline typename __outermost_type<_Alloc>::type& 00105 __outermost(_Alloc& __a) 00106 { return __outermost_type<_Alloc>::_S_outermost(__a); } 00107 00108 template<typename _OuterAlloc, typename... _InnerAllocs> 00109 class scoped_allocator_adaptor; 00110 00111 template<typename...> 00112 struct __inner_type_impl; 00113 00114 template<typename _Outer> 00115 struct __inner_type_impl<_Outer> 00116 { 00117 typedef scoped_allocator_adaptor<_Outer> __type; 00118 00119 __inner_type_impl() = default; 00120 __inner_type_impl(const __inner_type_impl&) = default; 00121 __inner_type_impl(__inner_type_impl&&) = default; 00122 __inner_type_impl& operator=(const __inner_type_impl&) = default; 00123 __inner_type_impl& operator=(__inner_type_impl&&) = default; 00124 00125 template<typename _Alloc> 00126 __inner_type_impl(const __inner_type_impl<_Alloc>& __other) 00127 { } 00128 00129 template<typename _Alloc> 00130 __inner_type_impl(__inner_type_impl<_Alloc>&& __other) 00131 { } 00132 00133 __type& 00134 _M_get(__type* __p) noexcept { return *__p; } 00135 00136 const __type& 00137 _M_get(const __type* __p) const noexcept { return *__p; } 00138 00139 tuple<> 00140 _M_tie() const noexcept { return tuple<>(); } 00141 00142 bool 00143 operator==(const __inner_type_impl&) const noexcept 00144 { return true; } 00145 }; 00146 00147 template<typename _Outer, typename _InnerHead, typename... _InnerTail> 00148 struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> 00149 { 00150 typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; 00151 00152 __inner_type_impl() = default; 00153 __inner_type_impl(const __inner_type_impl&) = default; 00154 __inner_type_impl(__inner_type_impl&&) = default; 00155 __inner_type_impl& operator=(const __inner_type_impl&) = default; 00156 __inner_type_impl& operator=(__inner_type_impl&&) = default; 00157 00158 template<typename... _Allocs> 00159 __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) 00160 : _M_inner(__other._M_inner) { } 00161 00162 template<typename... _Allocs> 00163 __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) 00164 : _M_inner(std::move(__other._M_inner)) { } 00165 00166 template<typename... _Args> 00167 explicit 00168 __inner_type_impl(_Args&&... __args) 00169 : _M_inner(std::forward<_Args>(__args)...) { } 00170 00171 __type& 00172 _M_get(void*) noexcept { return _M_inner; } 00173 00174 const __type& 00175 _M_get(const void*) const noexcept { return _M_inner; } 00176 00177 tuple<const _InnerHead&, const _InnerTail&...> 00178 _M_tie() const noexcept 00179 { return _M_inner._M_tie(); } 00180 00181 bool 00182 operator==(const __inner_type_impl& __other) const noexcept 00183 { return _M_inner == __other._M_inner; } 00184 00185 private: 00186 template<typename...> friend class __inner_type_impl; 00187 template<typename, typename...> friend class scoped_allocator_adaptor; 00188 00189 __type _M_inner; 00190 }; 00191 00192 /// Primary class template. 00193 template<typename _OuterAlloc, typename... _InnerAllocs> 00194 class scoped_allocator_adaptor 00195 : public _OuterAlloc 00196 { 00197 typedef allocator_traits<_OuterAlloc> __traits; 00198 00199 typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; 00200 __inner_type _M_inner; 00201 00202 template<typename _Outer, typename... _Inner> 00203 friend class scoped_allocator_adaptor; 00204 00205 template<typename...> 00206 friend class __inner_type_impl; 00207 00208 tuple<const _OuterAlloc&, const _InnerAllocs&...> 00209 _M_tie() const noexcept 00210 { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } 00211 00212 template<typename _Alloc> 00213 using __outermost_alloc_traits 00214 = allocator_traits<typename __outermost_type<_Alloc>::type>; 00215 00216 template<typename _Tp, typename... _Args> 00217 void 00218 _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) 00219 { 00220 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00221 _O_traits::construct(__outermost(*this), __p, 00222 std::forward<_Args>(__args)...); 00223 } 00224 00225 typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_; 00226 typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_; 00227 00228 template<typename _Tp, typename... _Args> 00229 void 00230 _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) 00231 { 00232 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00233 _O_traits::construct(__outermost(*this), __p, 00234 allocator_arg, inner_allocator(), 00235 std::forward<_Args>(__args)...); 00236 } 00237 00238 template<typename _Tp, typename... _Args> 00239 void 00240 _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) 00241 { 00242 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00243 _O_traits::construct(__outermost(*this), __p, 00244 std::forward<_Args>(__args)..., 00245 inner_allocator()); 00246 } 00247 00248 template<typename _Alloc> 00249 static _Alloc 00250 _S_select_on_copy(const _Alloc& __a) 00251 { 00252 typedef allocator_traits<_Alloc> __a_traits; 00253 return __a_traits::select_on_container_copy_construction(__a); 00254 } 00255 00256 template<std::size_t... _Indices> 00257 scoped_allocator_adaptor(tuple<const _OuterAlloc&, 00258 const _InnerAllocs&...> __refs, 00259 _Index_tuple<_Indices...>) 00260 : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), 00261 _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) 00262 { } 00263 00264 // Used to constrain constructors to disallow invalid conversions. 00265 template<typename _Alloc> 00266 using _Constructible = typename enable_if< 00267 is_constructible<_OuterAlloc, _Alloc>::value 00268 >::type; 00269 00270 public: 00271 typedef _OuterAlloc outer_allocator_type; 00272 typedef typename __inner_type::__type inner_allocator_type; 00273 00274 typedef typename __traits::value_type value_type; 00275 typedef typename __traits::size_type size_type; 00276 typedef typename __traits::difference_type difference_type; 00277 typedef typename __traits::pointer pointer; 00278 typedef typename __traits::const_pointer const_pointer; 00279 typedef typename __traits::void_pointer void_pointer; 00280 typedef typename __traits::const_void_pointer const_void_pointer; 00281 00282 typedef typename conditional< 00283 __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value, 00284 true_type, false_type>::type propagate_on_container_copy_assignment; 00285 typedef typename conditional< 00286 __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value, 00287 true_type, false_type>::type propagate_on_container_move_assignment; 00288 typedef typename conditional< 00289 __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value, 00290 true_type, false_type>::type propagate_on_container_swap; 00291 00292 template <class _Tp> 00293 struct rebind 00294 { 00295 typedef scoped_allocator_adaptor< 00296 typename __traits::template rebind_alloc<_Tp>, 00297 _InnerAllocs...> other; 00298 }; 00299 00300 scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } 00301 00302 template<typename _Outer2, typename = _Constructible<_Outer2>> 00303 scoped_allocator_adaptor(_Outer2&& __outer, 00304 const _InnerAllocs&... __inner) 00305 : _OuterAlloc(std::forward<_Outer2>(__outer)), 00306 _M_inner(__inner...) 00307 { } 00308 00309 scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) 00310 : _OuterAlloc(__other.outer_allocator()), 00311 _M_inner(__other._M_inner) 00312 { } 00313 00314 scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) 00315 : _OuterAlloc(std::move(__other.outer_allocator())), 00316 _M_inner(std::move(__other._M_inner)) 00317 { } 00318 00319 template<typename _Outer2, typename = _Constructible<const _Outer2&>> 00320 scoped_allocator_adaptor( 00321 const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) 00322 : _OuterAlloc(__other.outer_allocator()), 00323 _M_inner(__other._M_inner) 00324 { } 00325 00326 template<typename _Outer2, typename = _Constructible<_Outer2>> 00327 scoped_allocator_adaptor( 00328 scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) 00329 : _OuterAlloc(std::move(__other.outer_allocator())), 00330 _M_inner(std::move(__other._M_inner)) 00331 { } 00332 00333 scoped_allocator_adaptor& 00334 operator=(const scoped_allocator_adaptor&) = default; 00335 00336 scoped_allocator_adaptor& 00337 operator=(scoped_allocator_adaptor&&) = default; 00338 00339 inner_allocator_type& inner_allocator() noexcept 00340 { return _M_inner._M_get(this); } 00341 00342 const inner_allocator_type& inner_allocator() const noexcept 00343 { return _M_inner._M_get(this); } 00344 00345 outer_allocator_type& outer_allocator() noexcept 00346 { return static_cast<_OuterAlloc&>(*this); } 00347 00348 const outer_allocator_type& outer_allocator() const noexcept 00349 { return static_cast<const _OuterAlloc&>(*this); } 00350 00351 pointer allocate(size_type __n) 00352 { return __traits::allocate(outer_allocator(), __n); } 00353 00354 pointer allocate(size_type __n, const_void_pointer __hint) 00355 { return __traits::allocate(outer_allocator(), __n, __hint); } 00356 00357 void deallocate(pointer __p, size_type __n) 00358 { return __traits::deallocate(outer_allocator(), __p, __n); } 00359 00360 size_type max_size() const 00361 { return __traits::max_size(outer_allocator()); } 00362 00363 template<typename _Tp, typename... _Args> 00364 void construct(_Tp* __p, _Args&&... __args) 00365 { 00366 auto& __inner = inner_allocator(); 00367 auto __use_tag 00368 = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); 00369 _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); 00370 } 00371 00372 template<typename _T1, typename _T2, typename... _Args1, 00373 typename... _Args2> 00374 void 00375 construct(pair<_T1, _T2>* __p, piecewise_construct_t, 00376 tuple<_Args1...> __x, tuple<_Args2...> __y) 00377 { 00378 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00379 // 2203. wrong argument types for piecewise construction 00380 auto& __inner = inner_allocator(); 00381 auto __x_use_tag 00382 = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); 00383 auto __y_use_tag 00384 = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); 00385 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00386 _O_traits::construct(__outermost(*this), __p, piecewise_construct, 00387 _M_construct_p(__x_use_tag, __x), 00388 _M_construct_p(__y_use_tag, __y)); 00389 } 00390 00391 template<typename _T1, typename _T2> 00392 void 00393 construct(pair<_T1, _T2>* __p) 00394 { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } 00395 00396 template<typename _T1, typename _T2, typename _Up, typename _Vp> 00397 void 00398 construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) 00399 { 00400 construct(__p, piecewise_construct, 00401 std::forward_as_tuple(std::forward<_Up>(__u)), 00402 std::forward_as_tuple(std::forward<_Vp>(__v))); 00403 } 00404 00405 template<typename _T1, typename _T2, typename _Up, typename _Vp> 00406 void 00407 construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) 00408 { 00409 construct(__p, piecewise_construct, 00410 std::forward_as_tuple(__x.first), 00411 std::forward_as_tuple(__x.second)); 00412 } 00413 00414 template<typename _T1, typename _T2, typename _Up, typename _Vp> 00415 void 00416 construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) 00417 { 00418 construct(__p, piecewise_construct, 00419 std::forward_as_tuple(std::forward<_Up>(__x.first)), 00420 std::forward_as_tuple(std::forward<_Vp>(__x.second))); 00421 } 00422 00423 template<typename _Tp> 00424 void destroy(_Tp* __p) 00425 { 00426 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00427 _O_traits::destroy(__outermost(*this), __p); 00428 } 00429 00430 scoped_allocator_adaptor 00431 select_on_container_copy_construction() const 00432 { 00433 typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type 00434 _Indices; 00435 return scoped_allocator_adaptor(_M_tie(), _Indices()); 00436 } 00437 00438 template <typename _OutA1, typename _OutA2, typename... _InA> 00439 friend bool 00440 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 00441 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; 00442 00443 private: 00444 template<typename _Tuple> 00445 _Tuple&& 00446 _M_construct_p(__uses_alloc0, _Tuple& __t) 00447 { return std::move(__t); } 00448 00449 template<typename... _Args> 00450 std::tuple<allocator_arg_t, inner_allocator_type&, _Args...> 00451 _M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t) 00452 { 00453 typedef std::tuple<allocator_arg_t, inner_allocator_type&> _Tuple; 00454 return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()), 00455 std::move(__t)); 00456 } 00457 00458 template<typename... _Args> 00459 std::tuple<_Args..., inner_allocator_type&> 00460 _M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t) 00461 { 00462 typedef std::tuple<inner_allocator_type&> _Tuple; 00463 return std::tuple_cat(std::move(__t), _Tuple(inner_allocator())); 00464 } 00465 }; 00466 00467 template <typename _OutA1, typename _OutA2, typename... _InA> 00468 inline bool 00469 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 00470 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 00471 { 00472 return __a.outer_allocator() == __b.outer_allocator() 00473 && __a._M_inner == __b._M_inner; 00474 } 00475 00476 template <typename _OutA1, typename _OutA2, typename... _InA> 00477 inline bool 00478 operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 00479 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 00480 { return !(__a == __b); } 00481 00482 /// @} 00483 00484 _GLIBCXX_END_NAMESPACE_VERSION 00485 } // namespace 00486 00487 #endif // C++11 00488 00489 #endif // _SCOPED_ALLOCATOR