libstdc++
|
00001 // <scoped_allocator> -*- C++ -*- 00002 00003 // Copyright (C) 2011-2013 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 00078 template<typename _Alloc> 00079 inline auto 00080 __do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator()) 00081 { return __a.outer_allocator(); } 00082 00083 template<typename _Alloc> 00084 inline _Alloc& 00085 __do_outermost(_Alloc& __a, ...) 00086 { return __a; } 00087 00088 // TODO: make recursive (see note in 20.12.4/1) 00089 template<typename _Alloc> 00090 inline auto 00091 __outermost(_Alloc& __a) -> decltype(__do_outermost(__a, &__a)) 00092 { return __do_outermost(__a, &__a); } 00093 00094 template<typename _OuterAlloc, typename... _InnerAllocs> 00095 class scoped_allocator_adaptor; 00096 00097 template<typename...> 00098 struct __inner_type_impl; 00099 00100 template<typename _Outer> 00101 struct __inner_type_impl<_Outer> 00102 { 00103 typedef scoped_allocator_adaptor<_Outer> __type; 00104 00105 __inner_type_impl() = default; 00106 __inner_type_impl(const __inner_type_impl&) = default; 00107 __inner_type_impl(__inner_type_impl&&) = default; 00108 00109 template<typename _Alloc> 00110 __inner_type_impl(const __inner_type_impl<_Alloc>& __other) 00111 { } 00112 00113 template<typename _Alloc> 00114 __inner_type_impl(__inner_type_impl<_Alloc>&& __other) 00115 { } 00116 00117 __type& 00118 _M_get(__type* __p) noexcept { return *__p; } 00119 00120 const __type& 00121 _M_get(const __type* __p) const noexcept { return *__p; } 00122 00123 tuple<> 00124 _M_tie() const noexcept { return tuple<>(); } 00125 00126 bool 00127 operator==(const __inner_type_impl&) const noexcept 00128 { return true; } 00129 }; 00130 00131 template<typename _Outer, typename _InnerHead, typename... _InnerTail> 00132 struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> 00133 { 00134 typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; 00135 00136 __inner_type_impl() = default; 00137 __inner_type_impl(const __inner_type_impl&) = default; 00138 __inner_type_impl(__inner_type_impl&&) = default; 00139 00140 template<typename... _Allocs> 00141 __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) 00142 : _M_inner(__other._M_inner) { } 00143 00144 template<typename... _Allocs> 00145 __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) 00146 : _M_inner(std::move(__other._M_inner)) { } 00147 00148 template<typename... _Args> 00149 explicit 00150 __inner_type_impl(_Args&&... __args) 00151 : _M_inner(std::forward<_Args>(__args)...) { } 00152 00153 __type& 00154 _M_get(void*) noexcept { return _M_inner; } 00155 00156 const __type& 00157 _M_get(const void*) const noexcept { return _M_inner; } 00158 00159 tuple<const _InnerHead&, const _InnerTail&...> 00160 _M_tie() const noexcept 00161 { return _M_inner._M_tie(); } 00162 00163 bool 00164 operator==(const __inner_type_impl& __other) const noexcept 00165 { return _M_inner == __other._M_inner; } 00166 00167 private: 00168 template<typename...> friend class __inner_type_impl; 00169 template<typename, typename...> friend class scoped_allocator_adaptor; 00170 00171 __type _M_inner; 00172 }; 00173 00174 /// Primary class template. 00175 template<typename _OuterAlloc, typename... _InnerAllocs> 00176 class scoped_allocator_adaptor 00177 : public _OuterAlloc 00178 { 00179 typedef allocator_traits<_OuterAlloc> __traits; 00180 00181 typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; 00182 __inner_type _M_inner; 00183 00184 template<typename _Outer, typename... _Inner> 00185 friend class scoped_allocator_adaptor; 00186 00187 template<typename...> 00188 friend class __inner_type_impl; 00189 00190 tuple<const _OuterAlloc&, const _InnerAllocs&...> 00191 _M_tie() const noexcept 00192 { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } 00193 00194 template<typename _Alloc> 00195 using __outermost_type = typename 00196 std::decay<decltype(__outermost(std::declval<_Alloc&>()))>::type; 00197 00198 template<typename _Alloc> 00199 using __outermost_alloc_traits 00200 = allocator_traits<__outermost_type<_Alloc>>; 00201 00202 template<typename _Tp, typename... _Args> 00203 void 00204 _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) 00205 { 00206 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00207 _O_traits::construct(__outermost(*this), __p, 00208 std::forward<_Args>(__args)...); 00209 } 00210 00211 typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_; 00212 typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_; 00213 00214 template<typename _Tp, typename... _Args> 00215 void 00216 _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) 00217 { 00218 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00219 _O_traits::construct(__outermost(*this), __p, 00220 allocator_arg, inner_allocator(), 00221 std::forward<_Args>(__args)...); 00222 } 00223 00224 template<typename _Tp, typename... _Args> 00225 void 00226 _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) 00227 { 00228 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00229 _O_traits::construct(__outermost(*this), __p, 00230 std::forward<_Args>(__args)..., 00231 inner_allocator()); 00232 } 00233 00234 template<typename _Alloc> 00235 static _Alloc 00236 _S_select_on_copy(const _Alloc& __a) 00237 { 00238 typedef allocator_traits<_Alloc> __a_traits; 00239 return __a_traits::select_on_container_copy_construction(__a); 00240 } 00241 00242 template<std::size_t... _Indices> 00243 scoped_allocator_adaptor(tuple<const _OuterAlloc&, 00244 const _InnerAllocs&...> __refs, 00245 _Index_tuple<_Indices...>) 00246 : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), 00247 _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) 00248 { } 00249 00250 public: 00251 typedef _OuterAlloc outer_allocator_type; 00252 typedef typename __inner_type::__type inner_allocator_type; 00253 00254 typedef typename __traits::value_type value_type; 00255 typedef typename __traits::size_type size_type; 00256 typedef typename __traits::difference_type difference_type; 00257 typedef typename __traits::pointer pointer; 00258 typedef typename __traits::const_pointer const_pointer; 00259 typedef typename __traits::void_pointer void_pointer; 00260 typedef typename __traits::const_void_pointer const_void_pointer; 00261 00262 typedef typename conditional< 00263 __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value, 00264 true_type, false_type>::type propagate_on_container_copy_assignment; 00265 typedef typename conditional< 00266 __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value, 00267 true_type, false_type>::type propagate_on_container_move_assignment; 00268 typedef typename conditional< 00269 __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value, 00270 true_type, false_type>::type propagate_on_container_swap; 00271 00272 template <class _Tp> 00273 struct rebind 00274 { 00275 typedef scoped_allocator_adaptor< 00276 typename __traits::template rebind_alloc<_Tp>, 00277 _InnerAllocs...> other; 00278 }; 00279 00280 scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } 00281 00282 template<typename _Outer2> 00283 scoped_allocator_adaptor(_Outer2&& __outer, 00284 const _InnerAllocs&... __inner) 00285 : _OuterAlloc(std::forward<_Outer2>(__outer)), 00286 _M_inner(__inner...) 00287 { } 00288 00289 scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) 00290 : _OuterAlloc(__other.outer_allocator()), 00291 _M_inner(__other._M_inner) 00292 { } 00293 00294 scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) 00295 : _OuterAlloc(std::move(__other.outer_allocator())), 00296 _M_inner(std::move(__other._M_inner)) 00297 { } 00298 00299 template<typename _Outer2> 00300 scoped_allocator_adaptor( 00301 const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) 00302 : _OuterAlloc(__other.outer_allocator()), 00303 _M_inner(__other._M_inner) 00304 { } 00305 00306 template<typename _Outer2> 00307 scoped_allocator_adaptor( 00308 scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) 00309 : _OuterAlloc(std::move(__other.outer_allocator())), 00310 _M_inner(std::move(__other._M_inner)) 00311 { } 00312 00313 inner_allocator_type& inner_allocator() noexcept 00314 { return _M_inner._M_get(this); } 00315 00316 const inner_allocator_type& inner_allocator() const noexcept 00317 { return _M_inner._M_get(this); } 00318 00319 outer_allocator_type& outer_allocator() noexcept 00320 { return static_cast<_OuterAlloc&>(*this); } 00321 00322 const outer_allocator_type& outer_allocator() const noexcept 00323 { return static_cast<const _OuterAlloc&>(*this); } 00324 00325 pointer allocate(size_type __n) 00326 { return __traits::allocate(outer_allocator(), __n); } 00327 00328 pointer allocate(size_type __n, const_void_pointer __hint) 00329 { return __traits::allocate(outer_allocator(), __n, __hint); } 00330 00331 void deallocate(pointer __p, size_type __n) 00332 { return __traits::deallocate(outer_allocator(), __p, __n); } 00333 00334 size_type max_size() const 00335 { return __traits::max_size(outer_allocator()); } 00336 00337 template<typename _Tp, typename... _Args> 00338 void construct(_Tp* __p, _Args&&... __args) 00339 { 00340 auto& __inner = inner_allocator(); 00341 auto __use_tag 00342 = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); 00343 _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); 00344 } 00345 00346 template<typename _T1, typename _T2, typename... _Args1, 00347 typename... _Args2> 00348 void 00349 construct(pair<_T1, _T2>* __p, piecewise_construct_t, 00350 tuple<_Args1...> __x, tuple<_Args2...> __y) 00351 { 00352 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00353 // 2203. wrong argument types for piecewise construction 00354 auto& __inner = inner_allocator(); 00355 auto __x_use_tag 00356 = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); 00357 auto __y_use_tag 00358 = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); 00359 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00360 _O_traits::construct(__outermost(*this), __p, piecewise_construct, 00361 _M_construct_p(__x_use_tag, __x), 00362 _M_construct_p(__y_use_tag, __y)); 00363 } 00364 00365 template<typename _T1, typename _T2> 00366 void 00367 construct(pair<_T1, _T2>* __p) 00368 { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } 00369 00370 template<typename _T1, typename _T2, typename _Up, typename _Vp> 00371 void 00372 construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) 00373 { 00374 construct(__p, piecewise_construct, 00375 std::forward_as_tuple(std::forward<_Up>(__u)), 00376 std::forward_as_tuple(std::forward<_Vp>(__v))); 00377 } 00378 00379 template<typename _T1, typename _T2, typename _Up, typename _Vp> 00380 void 00381 construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) 00382 { 00383 construct(__p, piecewise_construct, 00384 std::forward_as_tuple(__x.first), 00385 std::forward_as_tuple(__x.second)); 00386 } 00387 00388 template<typename _T1, typename _T2, typename _Up, typename _Vp> 00389 void 00390 construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) 00391 { 00392 construct(__p, piecewise_construct, 00393 std::forward_as_tuple(std::forward<_Up>(__x.first)), 00394 std::forward_as_tuple(std::forward<_Vp>(__x.second))); 00395 } 00396 00397 template<typename _Tp> 00398 void destroy(_Tp* __p) 00399 { 00400 typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; 00401 _O_traits::destroy(__outermost(*this), __p); 00402 } 00403 00404 scoped_allocator_adaptor 00405 select_on_container_copy_construction() const 00406 { 00407 typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type 00408 _Indices; 00409 return scoped_allocator_adaptor(_M_tie(), _Indices()); 00410 } 00411 00412 template <typename _OutA1, typename _OutA2, typename... _InA> 00413 friend bool 00414 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 00415 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; 00416 00417 private: 00418 template<typename _Tuple> 00419 _Tuple&& 00420 _M_construct_p(__uses_alloc0, _Tuple& __t) 00421 { return std::move(__t); } 00422 00423 template<typename... _Args> 00424 std::tuple<allocator_arg_t, inner_allocator_type&, _Args...> 00425 _M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t) 00426 { 00427 typedef std::tuple<allocator_arg_t, inner_allocator_type&> _Tuple; 00428 return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()), 00429 std::move(__t)); 00430 } 00431 00432 template<typename... _Args> 00433 std::tuple<_Args..., inner_allocator_type&> 00434 _M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t) 00435 { 00436 typedef std::tuple<inner_allocator_type&> _Tuple; 00437 return std::tuple_cat(std::move(__t), _Tuple(inner_allocator())); 00438 } 00439 }; 00440 00441 template <typename _OutA1, typename _OutA2, typename... _InA> 00442 inline bool 00443 operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 00444 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 00445 { 00446 return __a.outer_allocator() == __b.outer_allocator() 00447 && __a._M_inner == __b._M_inner; 00448 } 00449 00450 template <typename _OutA1, typename _OutA2, typename... _InA> 00451 inline bool 00452 operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, 00453 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept 00454 { return !(__a == __b); } 00455 00456 /// @} 00457 00458 _GLIBCXX_END_NAMESPACE_VERSION 00459 } // namespace 00460 00461 #endif // C++11 00462 00463 #endif // _SCOPED_ALLOCATOR