11debfc3dSmrg // Uses-allocator Construction -*- C++ -*-
21debfc3dSmrg
3*8feb0f0bSmrg // Copyright (C) 2010-2020 Free Software Foundation, Inc.
41debfc3dSmrg //
51debfc3dSmrg // This file is part of the GNU ISO C++ Library. This library is free
61debfc3dSmrg // software; you can redistribute it and/or modify it under the
71debfc3dSmrg // terms of the GNU General Public License as published by the
81debfc3dSmrg // Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg // any later version.
101debfc3dSmrg
111debfc3dSmrg // This library is distributed in the hope that it will be useful,
121debfc3dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141debfc3dSmrg // GNU General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg // Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg // permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg // 3.1, as published by the Free Software Foundation.
191debfc3dSmrg
201debfc3dSmrg // You should have received a copy of the GNU General Public License and
211debfc3dSmrg // a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
231debfc3dSmrg // <http://www.gnu.org/licenses/>.
241debfc3dSmrg
251debfc3dSmrg #ifndef _USES_ALLOCATOR_H
261debfc3dSmrg #define _USES_ALLOCATOR_H 1
271debfc3dSmrg
281debfc3dSmrg #if __cplusplus < 201103L
291debfc3dSmrg # include <bits/c++0x_warning.h>
301debfc3dSmrg #else
311debfc3dSmrg
321debfc3dSmrg #include <type_traits>
331debfc3dSmrg #include <bits/move.h>
341debfc3dSmrg
_GLIBCXX_VISIBILITY(default)351debfc3dSmrg namespace std _GLIBCXX_VISIBILITY(default)
361debfc3dSmrg {
371debfc3dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
381debfc3dSmrg
39c0a68be4Smrg // This is used for std::experimental::erased_type from Library Fundamentals.
401debfc3dSmrg struct __erased_type { };
411debfc3dSmrg
42c0a68be4Smrg // This also supports the "type-erased allocator" protocol from the
43c0a68be4Smrg // Library Fundamentals TS, where allocator_type is erased_type.
44c0a68be4Smrg // The second condition will always be false for types not using the TS.
451debfc3dSmrg template<typename _Alloc, typename _Tp>
461debfc3dSmrg using __is_erased_or_convertible
47c0a68be4Smrg = __or_<is_convertible<_Alloc, _Tp>, is_same<_Tp, __erased_type>>;
481debfc3dSmrg
491debfc3dSmrg /// [allocator.tag]
501debfc3dSmrg struct allocator_arg_t { explicit allocator_arg_t() = default; };
511debfc3dSmrg
521debfc3dSmrg _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg =
531debfc3dSmrg allocator_arg_t();
541debfc3dSmrg
551debfc3dSmrg template<typename _Tp, typename _Alloc, typename = __void_t<>>
561debfc3dSmrg struct __uses_allocator_helper
571debfc3dSmrg : false_type { };
581debfc3dSmrg
591debfc3dSmrg template<typename _Tp, typename _Alloc>
601debfc3dSmrg struct __uses_allocator_helper<_Tp, _Alloc,
611debfc3dSmrg __void_t<typename _Tp::allocator_type>>
621debfc3dSmrg : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
631debfc3dSmrg { };
641debfc3dSmrg
651debfc3dSmrg /// [allocator.uses.trait]
661debfc3dSmrg template<typename _Tp, typename _Alloc>
671debfc3dSmrg struct uses_allocator
681debfc3dSmrg : __uses_allocator_helper<_Tp, _Alloc>::type
691debfc3dSmrg { };
701debfc3dSmrg
711debfc3dSmrg struct __uses_alloc_base { };
721debfc3dSmrg
731debfc3dSmrg struct __uses_alloc0 : __uses_alloc_base
741debfc3dSmrg {
75*8feb0f0bSmrg struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a;
761debfc3dSmrg };
771debfc3dSmrg
781debfc3dSmrg template<typename _Alloc>
791debfc3dSmrg struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
801debfc3dSmrg
811debfc3dSmrg template<typename _Alloc>
821debfc3dSmrg struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
831debfc3dSmrg
841debfc3dSmrg template<bool, typename _Tp, typename _Alloc, typename... _Args>
851debfc3dSmrg struct __uses_alloc;
861debfc3dSmrg
871debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
881debfc3dSmrg struct __uses_alloc<true, _Tp, _Alloc, _Args...>
891debfc3dSmrg : conditional<
90a2dc1f3fSmrg is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value,
911debfc3dSmrg __uses_alloc1<_Alloc>,
921debfc3dSmrg __uses_alloc2<_Alloc>>::type
931debfc3dSmrg {
94a2dc1f3fSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
95a2dc1f3fSmrg // 2586. Wrong value category used in scoped_allocator_adaptor::construct
961debfc3dSmrg static_assert(__or_<
97a2dc1f3fSmrg is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>,
98a2dc1f3fSmrg is_constructible<_Tp, _Args..., const _Alloc&>>::value,
99a2dc1f3fSmrg "construction with an allocator must be possible"
100a2dc1f3fSmrg " if uses_allocator is true");
1011debfc3dSmrg };
1021debfc3dSmrg
1031debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1041debfc3dSmrg struct __uses_alloc<false, _Tp, _Alloc, _Args...>
1051debfc3dSmrg : __uses_alloc0 { };
1061debfc3dSmrg
1071debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1081debfc3dSmrg using __uses_alloc_t =
1091debfc3dSmrg __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
1101debfc3dSmrg
1111debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
112*8feb0f0bSmrg _GLIBCXX20_CONSTEXPR
1131debfc3dSmrg inline __uses_alloc_t<_Tp, _Alloc, _Args...>
1141debfc3dSmrg __use_alloc(const _Alloc& __a)
1151debfc3dSmrg {
1161debfc3dSmrg __uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
1171debfc3dSmrg __ret._M_a = std::__addressof(__a);
1181debfc3dSmrg return __ret;
1191debfc3dSmrg }
1201debfc3dSmrg
1211debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1221debfc3dSmrg void
1231debfc3dSmrg __use_alloc(const _Alloc&&) = delete;
1241debfc3dSmrg
1251debfc3dSmrg #if __cplusplus > 201402L
1261debfc3dSmrg template <typename _Tp, typename _Alloc>
1271debfc3dSmrg inline constexpr bool uses_allocator_v =
1281debfc3dSmrg uses_allocator<_Tp, _Alloc>::value;
1291debfc3dSmrg #endif // C++17
1301debfc3dSmrg
1311debfc3dSmrg template<template<typename...> class _Predicate,
1321debfc3dSmrg typename _Tp, typename _Alloc, typename... _Args>
1331debfc3dSmrg struct __is_uses_allocator_predicate
1341debfc3dSmrg : conditional<uses_allocator<_Tp, _Alloc>::value,
1351debfc3dSmrg __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
1361debfc3dSmrg _Predicate<_Tp, _Args..., _Alloc>>,
1371debfc3dSmrg _Predicate<_Tp, _Args...>>::type { };
1381debfc3dSmrg
1391debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1401debfc3dSmrg struct __is_uses_allocator_constructible
1411debfc3dSmrg : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...>
1421debfc3dSmrg { };
1431debfc3dSmrg
1441debfc3dSmrg #if __cplusplus >= 201402L
1451debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1461debfc3dSmrg _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v =
1471debfc3dSmrg __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
1481debfc3dSmrg #endif // C++14
1491debfc3dSmrg
1501debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1511debfc3dSmrg struct __is_nothrow_uses_allocator_constructible
1521debfc3dSmrg : __is_uses_allocator_predicate<is_nothrow_constructible,
1531debfc3dSmrg _Tp, _Alloc, _Args...>
1541debfc3dSmrg { };
1551debfc3dSmrg
1561debfc3dSmrg
1571debfc3dSmrg #if __cplusplus >= 201402L
1581debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1591debfc3dSmrg _GLIBCXX17_INLINE constexpr bool
1601debfc3dSmrg __is_nothrow_uses_allocator_constructible_v =
1611debfc3dSmrg __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
1621debfc3dSmrg #endif // C++14
1631debfc3dSmrg
1641debfc3dSmrg template<typename _Tp, typename... _Args>
1651debfc3dSmrg void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr,
1661debfc3dSmrg _Args&&... __args)
1671debfc3dSmrg { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); }
1681debfc3dSmrg
1691debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1701debfc3dSmrg void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr,
1711debfc3dSmrg _Args&&... __args)
1721debfc3dSmrg {
1731debfc3dSmrg ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a,
1741debfc3dSmrg std::forward<_Args>(__args)...);
1751debfc3dSmrg }
1761debfc3dSmrg
1771debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1781debfc3dSmrg void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr,
1791debfc3dSmrg _Args&&... __args)
1801debfc3dSmrg { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); }
1811debfc3dSmrg
1821debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
1831debfc3dSmrg void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
1841debfc3dSmrg _Args&&... __args)
1851debfc3dSmrg {
186c0a68be4Smrg std::__uses_allocator_construct_impl(
187c0a68be4Smrg std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr,
188c0a68be4Smrg std::forward<_Args>(__args)...);
1891debfc3dSmrg }
1901debfc3dSmrg
1911debfc3dSmrg _GLIBCXX_END_NAMESPACE_VERSION
1921debfc3dSmrg } // namespace std
1931debfc3dSmrg
1941debfc3dSmrg #endif
1951debfc3dSmrg #endif
196