libstdc++
uses_allocator.h
1// Uses-allocator Construction -*- C++ -*-
2
3// Copyright (C) 2010-2025 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/bits/uses_allocator_args.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _USES_ALLOCATOR_H
31#define _USES_ALLOCATOR_H 1
32
33#if __cplusplus < 201103L
34# include <bits/c++0x_warning.h>
35#else
36
37#include <type_traits>
38#include <bits/move.h>
39
40namespace std _GLIBCXX_VISIBILITY(default)
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43/// @cond undocumented
44
45 // This is used for std::experimental::erased_type from Library Fundamentals.
46 struct __erased_type { };
47
48 // This also supports the "type-erased allocator" protocol from the
49 // Library Fundamentals TS, where allocator_type is erased_type.
50 // The second condition will always be false for types not using the TS.
51 template<typename _Alloc, typename _Tp>
52 using __is_erased_or_convertible
53 = __or_<is_convertible<_Alloc, _Tp>, is_same<_Tp, __erased_type>>;
54
55 /// [allocator.tag]
56 struct allocator_arg_t { explicit allocator_arg_t() = default; };
57
58 _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg =
59 allocator_arg_t();
60
61 template<typename _Tp, typename _Alloc, typename = __void_t<>>
62 struct __uses_allocator_helper
63 : false_type { };
64
65 template<typename _Tp, typename _Alloc>
66 struct __uses_allocator_helper<_Tp, _Alloc,
67 __void_t<typename _Tp::allocator_type>>
68 : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
69 { };
70
71 /// [allocator.uses.trait]
72 template<typename _Tp, typename _Alloc>
73 struct uses_allocator
74 : __uses_allocator_helper<_Tp, _Alloc>::type
75 { };
76
77 struct __uses_alloc_base { };
78
79 struct __uses_alloc0 : __uses_alloc_base
80 {
81 struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a;
82 };
83
84 template<typename _Alloc>
85 struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
86
87 template<typename _Alloc>
88 struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
89
90 template<bool, typename _Tp, typename _Alloc, typename... _Args>
91 struct __uses_alloc;
92
93 template<typename _Tp, typename _Alloc, typename... _Args>
94 struct __uses_alloc<true, _Tp, _Alloc, _Args...>
95 : __conditional_t<
96 is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value,
97 __uses_alloc1<_Alloc>,
98 __uses_alloc2<_Alloc>>
99 {
100 // _GLIBCXX_RESOLVE_LIB_DEFECTS
101 // 2586. Wrong value category used in scoped_allocator_adaptor::construct
102 static_assert(__or_<
103 is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>,
104 is_constructible<_Tp, _Args..., const _Alloc&>>::value,
105 "construction with an allocator must be possible"
106 " if uses_allocator is true");
107 };
108
109 template<typename _Tp, typename _Alloc, typename... _Args>
110 struct __uses_alloc<false, _Tp, _Alloc, _Args...>
111 : __uses_alloc0 { };
112
113 template<typename _Tp, typename _Alloc, typename... _Args>
114 using __uses_alloc_t =
115 __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
116
117 template<typename _Tp, typename _Alloc, typename... _Args>
118 _GLIBCXX20_CONSTEXPR
119 inline __uses_alloc_t<_Tp, _Alloc, _Args...>
120 __use_alloc(const _Alloc& __a)
121 {
122 __uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
123 __ret._M_a = std::__addressof(__a);
124 return __ret;
125 }
126
127 template<typename _Tp, typename _Alloc, typename... _Args>
128 void
129 __use_alloc(const _Alloc&&) = delete;
130
131#if __cplusplus > 201402L
132 template <typename _Tp, typename _Alloc>
133 inline constexpr bool uses_allocator_v =
135#endif // C++17
136
137#if __cpp_concepts
138 template<typename _Alloc, typename... _Ts>
139 concept __allocator_for = (uses_allocator_v<_Ts, _Alloc> && ...);
140#endif
141
142 template<template<typename...> class _Predicate,
143 typename _Tp, typename _Alloc, typename... _Args>
144 struct __is_uses_allocator_predicate
145 : __conditional_t<uses_allocator<_Tp, _Alloc>::value,
146 __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
147 _Predicate<_Tp, _Args..., _Alloc>>,
148 _Predicate<_Tp, _Args...>> { };
149
150 template<typename _Tp, typename _Alloc, typename... _Args>
151 struct __is_uses_allocator_constructible
152 : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...>
153 { };
154
155#if __cplusplus >= 201402L
156 template<typename _Tp, typename _Alloc, typename... _Args>
157 _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v =
158 __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
159#endif // C++14
160
161 template<typename _Tp, typename _Alloc, typename... _Args>
162 struct __is_nothrow_uses_allocator_constructible
163 : __is_uses_allocator_predicate<is_nothrow_constructible,
164 _Tp, _Alloc, _Args...>
165 { };
166
167
168#if __cplusplus >= 201402L
169 template<typename _Tp, typename _Alloc, typename... _Args>
170 _GLIBCXX17_INLINE constexpr bool
171 __is_nothrow_uses_allocator_constructible_v =
172 __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
173#endif // C++14
174
175 template<typename _Tp, typename... _Args>
176 void __uses_allocator_construct_impl(__uses_alloc0, _Tp* __ptr,
177 _Args&&... __args)
178 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); }
179
180 template<typename _Tp, typename _Alloc, typename... _Args>
181 void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr,
182 _Args&&... __args)
183 {
184 ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a,
185 std::forward<_Args>(__args)...);
186 }
187
188 template<typename _Tp, typename _Alloc, typename... _Args>
189 void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr,
190 _Args&&... __args)
191 { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); }
192
193 template<typename _Tp, typename _Alloc, typename... _Args>
194 void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
195 _Args&&... __args)
196 {
197 std::__uses_allocator_construct_impl(
198 std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr,
199 std::forward<_Args>(__args)...);
200 }
201
202/// @endcond
203_GLIBCXX_END_NAMESPACE_VERSION
204} // namespace std
205
206#endif
207#endif
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:119
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:52
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
ISO C++ entities toplevel namespace is std.
Declare uses_allocator so it can be specialized in <queue> etc.
Definition memoryfwd.h:75