Go to the documentation of this file. 1// <concepts> -*- C++ -*-
3// Copyright (C) 2019-2025 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25/** @
file include/concepts
26 * This is a Standard C++ Library header.
30#ifndef _GLIBCXX_CONCEPTS
31#define _GLIBCXX_CONCEPTS 1
34#pragma GCC system_header
37#define __glibcxx_want_concepts
38#include <bits/version.h>
40#ifdef __cpp_lib_concepts // C++ >= 20 && concepts
42 * @
defgroup concepts Concepts
45 * Concepts for checking type requirements.
50namespace std _GLIBCXX_VISIBILITY(default)
52_GLIBCXX_BEGIN_NAMESPACE_VERSION
54 // [
concepts.lang]
, language-related concepts
58 template<typename _Tp, typename _Up>
59 concept __same_as = std::is_same_v<_Tp, _Up>;
60 }
// namespace __detail
62 /// [
concept.same]
, concept same_as
63 template<typename _Tp, typename _Up>
65 = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>;
69 template<typename _Tp, typename _Up>
70 concept __different_from
71 = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
72 }
// namespace __detail
74 /// [
concept.derived]
, concept derived_from
75 template<typename _Derived, typename _Base>
76 concept derived_from = __is_base_of(_Base, _Derived)
77 && is_convertible_v<const volatile _Derived*, const volatile _Base*>;
79 /// [
concept.convertible]
, concept convertible_to
80 template<typename _From, typename _To>
81 concept convertible_to = is_convertible_v<_From, _To>
82 && requires {
static_cast<_To>(std::declval<_From>()); };
84 /// [
concept.commonref]
, concept common_reference_with
85 template<typename _Tp, typename _Up>
86 concept common_reference_with
87 = same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>>
88 && convertible_to<_Tp, common_reference_t<_Tp, _Up>>
89 && convertible_to<_Up, common_reference_t<_Tp, _Up>>;
91 /// [
concept.common]
, concept common_with
92 template<typename _Tp, typename _Up>
94 = same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>>
96 static_cast<common_type_t<_Tp, _Up>>(std::declval<_Tp>());
97 static_cast<common_type_t<_Tp, _Up>>(std::declval<_Up>());
99 && common_reference_with<add_lvalue_reference_t<const _Tp>,
100 add_lvalue_reference_t<const _Up>>
101 && common_reference_with<add_lvalue_reference_t<common_type_t<_Tp, _Up>>,
103 add_lvalue_reference_t<const _Tp>,
104 add_lvalue_reference_t<const _Up>>>;
106 // [
concepts.arithmetic]
, arithmetic concepts
108 template<typename _Tp>
109 concept integral = is_integral_v<_Tp>;
111 template<typename _Tp>
112 concept signed_integral = integral<_Tp> && is_signed_v<_Tp>;
114 template<typename _Tp>
115 concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
117 template<typename _Tp>
118 concept floating_point = is_floating_point_v<_Tp>;
122 template<typename _Tp>
123 using __cref = const remove_reference_t<_Tp>&;
125 template<typename _Tp>
126 concept __class_or_enum
127 = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
129 template<typename _Tp>
130 constexpr bool __destructible_impl = false;
131 template<typename _Tp>
132 requires requires(_Tp& __t) { {
__t.~_Tp() }
noexcept; }
133 constexpr bool __destructible_impl<_Tp> = true;
135 template<typename _Tp>
136 constexpr bool __destructible = __destructible_impl<_Tp>;
137 template<typename _Tp>
138 constexpr bool __destructible<_Tp&> = true;
139 template<typename _Tp>
140 constexpr bool __destructible<_Tp&&> = true;
141 template<typename _Tp, size_t _Nm>
142 constexpr bool __destructible<_Tp[
_Nm]
> = __destructible<_Tp>;
144 }
// namespace __detail
146 /// [
concept.assignable]
, concept assignable_from
147 template<typename _Lhs, typename _Rhs>
148 concept assignable_from
149 = is_lvalue_reference_v<_Lhs>
150 && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>>
151 && requires(_Lhs __lhs, _Rhs&& __rhs) {
152 {
__lhs = static_cast<_Rhs&&>(__rhs) }
-> same_as<_Lhs>;
155 /// [
concept.destructible]
, concept destructible
156 template<typename _Tp>
157 concept destructible = __detail::__destructible<_Tp>;
159 /// [
concept.constructible]
, concept constructible_from
160 template<typename _Tp, typename... _Args>
161 concept constructible_from
162 = destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
164 /// [
concept.defaultinitializable]
, concept default_initializable
165 template<typename _Tp>
166 concept default_initializable = constructible_from<_Tp>
173 /// [
concept.moveconstructible]
, concept move_constructible
174 template<typename _Tp>
175 concept move_constructible
176 = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
178 /// [
concept.copyconstructible]
, concept copy_constructible
179 template<typename _Tp>
180 concept copy_constructible
181 = move_constructible<_Tp>
182 && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp>
183 && constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp>
184 && constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>;
186 // [
concept.swappable]
, concept swappable
190 /// @
cond undocumented
193 template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
195 template<typename _Tp, typename _Up>
197 = (std::__detail::__class_or_enum<remove_reference_t<_Tp>>
198 || std::__detail::__class_or_enum<remove_reference_t<_Up>>)
199 && requires(_Tp&& __t, _Up&& __u) {
200 swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
206 template<typename _Tp, typename _Up>
207 static consteval bool
210 if constexpr (__adl_swap<_Tp, _Up>)
211 return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()));
213 return is_nothrow_move_constructible_v<remove_reference_t<_Tp>>
214 && is_nothrow_move_assignable_v<remove_reference_t<_Tp>>;
218 template<typename _Tp, typename _Up>
219 requires __adl_swap<_Tp, _Up>
220 || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp>
221 && move_constructible<remove_reference_t<_Tp>>
222 && assignable_from<_Tp, remove_reference_t<_Tp>>)
224 operator()(_Tp&& __t, _Up&& __u) const
225 noexcept(_S_noexcept<_Tp, _Up>())
227 if constexpr (__adl_swap<_Tp, _Up>)
228 swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
231 auto __tmp = static_cast<remove_reference_t<_Tp>&&>(__t);
232 __t = static_cast<remove_reference_t<_Tp>&&>(__u);
233 __u = static_cast<remove_reference_t<_Tp>&&>(__tmp);
237 template<typename _Tp, typename _Up, size_t _Num>
238 requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) {
242 operator()(_Tp (&__e1)[
_Num]
, _Up (&__e2)[
_Num]
) const
243 noexcept(noexcept(std::declval<const _Swap&>()(*__e1, *__e2)))
245 for (size_t __n = 0;
__n < _Num;
++__n)
246 (*this)(__e1[
__n]
, __e2[
__n]
);
249 }
// namespace __swap
252 inline namespace _Cpo {
253 inline constexpr __swap::_Swap swap{};
255 }
// namespace ranges
257 template<typename _Tp>
259 = requires(_Tp& __a, _Tp& __b) {
ranges::swap(__a, __b); };
261 template<typename _Tp, typename _Up>
262 concept swappable_with = common_reference_with<_Tp, _Up>
263 && requires(_Tp&& __t, _Up&& __u) {
264 ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t));
265 ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u));
266 ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
267 ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t));
270 // [
concepts.object]
, Object concepts
272 template<typename _Tp>
273 concept movable = is_object_v<_Tp> && move_constructible<_Tp>
274 && assignable_from<_Tp&, _Tp> && swappable<_Tp>;
276 template<typename _Tp>
277 concept copyable = copy_constructible<_Tp> && movable<_Tp>
278 && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&>
279 && assignable_from<_Tp&, const _Tp>;
281 template<typename _Tp>
282 concept semiregular = copyable<_Tp> && default_initializable<_Tp>;
284 // [
concepts.compare]
, comparison concepts
286 // [
concept.booleantestable]
, Boolean testability
289 template<typename _Tp>
290 concept __boolean_testable_impl = convertible_to<_Tp, bool>;
292 template<typename _Tp>
293 concept __boolean_testable
294 = __boolean_testable_impl<_Tp>
295 && requires(_Tp&& __t)
296 { {
!static_cast<_Tp&&>(__t) }
-> __boolean_testable_impl; };
297 }
// namespace __detail
299 // [
concept.equalitycomparable]
, concept equality_comparable
303 template<typename _Tp, typename _Up>
304 concept __weakly_eq_cmp_with
305 = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) {
306 {
__t == __u }
-> __boolean_testable;
307 {
__t != __u }
-> __boolean_testable;
308 {
__u == __t }
-> __boolean_testable;
309 {
__u != __t }
-> __boolean_testable;
311 }
// namespace __detail
313 template<typename _Tp>
314 concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>;
316 template<typename _Tp, typename _Up>
317 concept equality_comparable_with
318 = equality_comparable<_Tp> && equality_comparable<_Up>
319 && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>>
320 && equality_comparable<common_reference_t<__detail::__cref<_Tp>,
321 __detail::__cref<_Up>>>
322 && __detail::__weakly_eq_cmp_with<_Tp, _Up>;
326 template<typename _Tp, typename _Up>
327 concept __partially_ordered_with
328 = requires(const remove_reference_t<_Tp>& __t,
329 const remove_reference_t<_Up>& __u) {
330 {
__t < __u }
-> __boolean_testable;
331 {
__t > __u }
-> __boolean_testable;
332 {
__t <= __u }
-> __boolean_testable;
333 {
__t >= __u }
-> __boolean_testable;
334 {
__u < __t }
-> __boolean_testable;
335 {
__u > __t }
-> __boolean_testable;
336 {
__u <= __t }
-> __boolean_testable;
337 {
__u >= __t }
-> __boolean_testable;
339 }
// namespace __detail
341 // [
concept.totallyordered]
, concept totally_ordered
342 template<typename _Tp>
343 concept totally_ordered
344 = equality_comparable<_Tp>
345 && __detail::__partially_ordered_with<_Tp, _Tp>;
347 template<typename _Tp, typename _Up>
348 concept totally_ordered_with
349 = totally_ordered<_Tp> && totally_ordered<_Up>
350 && equality_comparable_with<_Tp, _Up>
351 && totally_ordered<common_reference_t<__detail::__cref<_Tp>,
352 __detail::__cref<_Up>>>
353 && __detail::__partially_ordered_with<_Tp, _Up>;
355 template<typename _Tp>
356 concept regular = semiregular<_Tp> && equality_comparable<_Tp>;
358 // [
concepts.callable]
, callable concepts
360 /// [
concept.invocable]
, concept invocable
361 template<typename _Fn, typename... _Args>
362 concept invocable = is_invocable_v<_Fn, _Args...>;
364 /// [
concept.regularinvocable]
, concept regular_invocable
365 template<typename _Fn, typename... _Args>
366 concept regular_invocable = invocable<_Fn, _Args...>;
368 /// [
concept.predicate]
, concept predicate
369 template<typename _Fn, typename... _Args>
370 concept predicate = regular_invocable<_Fn, _Args...>
371 && __detail::__boolean_testable<invoke_result_t<_Fn, _Args...>>;
373 /// [
concept.relation]
, concept relation
374 template<typename _Rel, typename _Tp, typename _Up>
376 = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up>
377 && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>;
379 /// [
concept.equiv]
, concept equivalence_relation
380 template<typename _Rel, typename _Tp, typename _Up>
381 concept equivalence_relation = relation<_Rel, _Tp, _Up>;
383 /// [
concept.strictweakorder]
, concept strict_weak_order
384 template<typename _Rel, typename _Tp, typename _Up>
385 concept strict_weak_order = relation<_Rel, _Tp, _Up>;
387_GLIBCXX_END_NAMESPACE_VERSION
389#endif // __cpp_lib_concepts
391#endif /* _GLIBCXX_CONCEPTS */