xref: /freebsd/contrib/llvm-project/libcxx/include/concepts (revision e87ec409fa9b21abf79895837fe375ab3d7e408a)
1// -*- C++ -*-
2//===-------------------------- concepts ----------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_CONCEPTS
11#define _LIBCPP_CONCEPTS
12
13/*
14    concepts synopsis
15namespace std {
16  // [concepts.lang], language-related concepts
17  // [concept.same], concept same_as
18  template<class T, class U>
19    concept same_as = see below;
20
21  // [concept.derived], concept derived_from
22  template<class Derived, class Base>
23    concept derived_from = see below;
24
25  // [concept.convertible], concept convertible_to
26  template<class From, class To>
27    concept convertible_to = see below;
28
29  // [concept.commonref], concept common_reference_with
30  template<class T, class U>
31    concept common_reference_with = see below;
32
33  // [concept.common], concept common_with
34  template<class T, class U>
35    concept common_with = see below;
36
37  // [concepts.arithmetic], arithmetic concepts
38  template<class T>
39    concept integral = see below;
40  template<class T>
41    concept signed_integral = see below;
42  template<class T>
43    concept unsigned_integral = see below;
44  template<class T>
45    concept floating_point = see below;
46
47  // [concept.assignable], concept assignable_from
48  template<class LHS, class RHS>
49    concept assignable_from = see below;
50
51  // [concept.swappable], concept swappable
52  namespace ranges {
53    inline namespace unspecified {
54      inline constexpr unspecified swap = unspecified;
55    }
56  }
57  template<class T>
58    concept swappable = see below;
59  template<class T, class U>
60    concept swappable_with = see below;
61
62  // [concept.destructible], concept destructible
63  template<class T>
64    concept destructible = see below;
65
66  // [concept.constructible], concept constructible_from
67  template<class T, class... Args>
68    concept constructible_from = see below;
69
70  // [concept.default.init], concept default_initializable
71  template<class T>
72    concept default_initializable = see below;
73
74  // [concept.moveconstructible], concept move_constructible
75  template<class T>
76    concept move_constructible = see below;
77
78  // [concept.copyconstructible], concept copy_constructible
79  template<class T>
80    concept copy_constructible = see below;
81
82  // [concept.equalitycomparable], concept equality_comparable
83  template<class T>
84    concept equality_comparable = see below;
85  template<class T, class U>
86    concept equality_comparable_with = see below;
87
88  // [concept.totallyordered], concept totally_ordered
89  template<class T>
90    concept totally_ordered = see below;
91  template<class T, class U>
92    concept totally_ordered_with = see below;
93
94  // [concepts.object], object concepts
95  template<class T>
96    concept movable = see below;
97  template<class T>
98    concept copyable = see below;
99  template<class T>
100    concept semiregular = see below;
101  template<class T>
102    concept regular = see below;
103
104  // [concepts.callable], callable concepts
105  // [concept.invocable], concept invocable
106  template<class F, class... Args>
107    concept invocable = see below;
108
109  // [concept.regularinvocable], concept regular_invocable
110  template<class F, class... Args>
111    concept regular_invocable = see below;
112
113  // [concept.predicate], concept predicate
114  template<class F, class... Args>
115    concept predicate = see below;
116
117  // [concept.relation], concept relation
118  template<class R, class T, class U>
119    concept relation = see below;
120
121  // [concept.equiv], concept equivalence_relation
122  template<class R, class T, class U>
123    concept equivalence_relation = see below;
124
125  // [concept.strictweakorder], concept strict_weak_order
126  template<class R, class T, class U>
127    concept strict_weak_order = see below;
128}
129
130*/
131
132#include <__config>
133#include <__functional/invoke.h>
134#include <__functional_base>
135#include <type_traits>
136#include <utility>
137#include <version>
138
139#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
140#pragma GCC system_header
141#endif
142
143_LIBCPP_PUSH_MACROS
144#include <__undef_macros>
145
146_LIBCPP_BEGIN_NAMESPACE_STD
147
148#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
149
150// [concept.same]
151
152template<class _Tp, class _Up>
153concept __same_as_impl = _VSTD::_IsSame<_Tp, _Up>::value;
154
155template<class _Tp, class _Up>
156concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;
157
158// [concept.derived]
159template<class _Dp, class _Bp>
160concept derived_from =
161  is_base_of_v<_Bp, _Dp> &&
162  is_convertible_v<const volatile _Dp*, const volatile _Bp*>;
163
164// [concept.convertible]
165template<class _From, class _To>
166concept convertible_to =
167  is_convertible_v<_From, _To> &&
168  requires(add_rvalue_reference_t<_From> (&__f)()) {
169    static_cast<_To>(__f());
170  };
171
172// [concept.commonref]
173template<class _Tp, class _Up>
174concept common_reference_with =
175  same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> &&
176  convertible_to<_Tp, common_reference_t<_Tp, _Up>> &&
177  convertible_to<_Up, common_reference_t<_Tp, _Up>>;
178
179// [concept.common]
180template<class _Tp, class _Up>
181concept common_with =
182  same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> &&
183  requires {
184    static_cast<common_type_t<_Tp, _Up>>(declval<_Tp>());
185    static_cast<common_type_t<_Tp, _Up>>(declval<_Up>());
186  } &&
187  common_reference_with<
188    add_lvalue_reference_t<const _Tp>,
189    add_lvalue_reference_t<const _Up>> &&
190  common_reference_with<
191    add_lvalue_reference_t<common_type_t<_Tp, _Up>>,
192    common_reference_t<
193      add_lvalue_reference_t<const _Tp>,
194      add_lvalue_reference_t<const _Up>>>;
195
196// [concepts.arithmetic], arithmetic concepts
197template<class _Tp>
198concept integral = is_integral_v<_Tp>;
199
200template<class _Tp>
201concept signed_integral = integral<_Tp> && is_signed_v<_Tp>;
202
203template<class _Tp>
204concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
205
206template<class _Tp>
207concept floating_point = is_floating_point_v<_Tp>;
208
209// [concept.assignable]
210template<class _Lhs, class _Rhs>
211concept assignable_from =
212  is_lvalue_reference_v<_Lhs> &&
213  common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> &&
214  requires (_Lhs __lhs, _Rhs&& __rhs) {
215    { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>;
216  };
217
218// [concept.destructible]
219
220template<class _Tp>
221concept destructible = is_nothrow_destructible_v<_Tp>;
222
223// [concept.constructible]
224template<class _Tp, class... _Args>
225concept constructible_from =
226    destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
227
228// [concept.default.init]
229
230template<class _Tp>
231concept __default_initializable = requires { ::new _Tp; };
232
233template<class _Tp>
234concept default_initializable = constructible_from<_Tp> &&
235    requires { _Tp{}; } && __default_initializable<_Tp>;
236
237// [concept.moveconstructible]
238template<class _Tp>
239concept move_constructible =
240  constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
241
242// [concept.copyconstructible]
243template<class _Tp>
244concept copy_constructible =
245  move_constructible<_Tp> &&
246  constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> &&
247  constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> &&
248  constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>;
249
250// Whether a type is a class type or enumeration type according to the Core wording.
251template<class _Tp>
252concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
253
254// [concept.swappable]
255namespace ranges::__swap {
256  // Deleted to inhibit ADL
257  template<class _Tp>
258  void swap(_Tp&, _Tp&) = delete;
259
260
261  // [1]
262  template<class _Tp, class _Up>
263  concept __unqualified_swappable_with =
264    (__class_or_enum<remove_cvref_t<_Tp>> || __class_or_enum<remove_cvref_t<_Up>>) &&
265    requires(_Tp&& __t, _Up&& __u) {
266      swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
267    };
268
269  struct __fn;
270
271  template<class _Tp, class _Up, size_t _Size>
272  concept __swappable_arrays =
273    !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> &&
274    extent_v<_Tp> == extent_v<_Up> &&
275    requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) {
276      __swap(__t[0], __u[0]);
277    };
278
279  template<class _Tp>
280  concept __exchangeable =
281    !__unqualified_swappable_with<_Tp&, _Tp&> &&
282    move_constructible<_Tp> &&
283    assignable_from<_Tp&, _Tp>;
284
285  struct __fn {
286    // 2.1   `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and...
287    // *The name `swap` is used here unqualified.
288    template<class _Tp, class _Up>
289    requires __unqualified_swappable_with<_Tp, _Up>
290    constexpr void operator()(_Tp&& __t, _Up&& __u) const
291    noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))
292    {
293      swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
294    }
295
296    // 2.2   Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and...
297    template<class _Tp, class _Up, size_t _Size>
298    requires __swappable_arrays<_Tp, _Up, _Size>
299    constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const
300    noexcept(noexcept((*this)(*__t, *__u)))
301    {
302      // TODO(cjdb): replace with `ranges::swap_ranges`.
303      for (size_t __i = 0; __i < _Size; ++__i) {
304        (*this)(__t[__i], __u[__i]);
305      }
306    }
307
308    // 2.3   Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models...
309    template<__exchangeable _Tp>
310    constexpr void operator()(_Tp& __x, _Tp& __y) const
311    noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>)
312    {
313      __y = _VSTD::exchange(__x, _VSTD::move(__y));
314    }
315  };
316} // namespace ranges::__swap
317
318namespace ranges::inline __cpo {
319  inline constexpr auto swap = __swap::__fn{};
320} // namespace ranges::__cpo
321
322template<class _Tp>
323concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); };
324
325template<class _Tp, class _Up>
326concept swappable_with =
327  common_reference_with<_Tp, _Up> &&
328  requires(_Tp&& __t, _Up&& __u) {
329    ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t));
330    ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u));
331    ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
332    ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t));
333  };
334
335// [concept.booleantestable]
336template<class _Tp>
337concept __boolean_testable_impl = convertible_to<_Tp, bool>;
338
339template<class _Tp>
340concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) {
341  { !std::forward<_Tp>(__t) } -> __boolean_testable_impl;
342};
343
344// [concept.equalitycomparable]
345template<class _Tp, class _Up>
346concept __weakly_equality_comparable_with =
347  requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
348    { __t == __u } -> __boolean_testable;
349    { __t != __u } -> __boolean_testable;
350    { __u == __t } -> __boolean_testable;
351    { __u != __t } -> __boolean_testable;
352  };
353
354template<class _Tp>
355concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
356
357template<class _Tp, class _Up>
358concept equality_comparable_with =
359  equality_comparable<_Tp> && equality_comparable<_Up> &&
360  common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
361  equality_comparable<
362    common_reference_t<
363      __make_const_lvalue_ref<_Tp>,
364      __make_const_lvalue_ref<_Up>>> &&
365  __weakly_equality_comparable_with<_Tp, _Up>;
366
367// [concept.totallyordered]
368
369template<class _Tp, class _Up>
370concept __partially_ordered_with =
371  requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
372    { __t <  __u } -> __boolean_testable;
373    { __t >  __u } -> __boolean_testable;
374    { __t <= __u } -> __boolean_testable;
375    { __t >= __u } -> __boolean_testable;
376    { __u <  __t } -> __boolean_testable;
377    { __u >  __t } -> __boolean_testable;
378    { __u <= __t } -> __boolean_testable;
379    { __u >= __t } -> __boolean_testable;
380  };
381
382template<class _Tp>
383concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>;
384
385template<class _Tp, class _Up>
386concept totally_ordered_with =
387  totally_ordered<_Tp> && totally_ordered<_Up> &&
388  equality_comparable_with<_Tp, _Up> &&
389  totally_ordered<
390    common_reference_t<
391      __make_const_lvalue_ref<_Tp>,
392      __make_const_lvalue_ref<_Up>>> &&
393  __partially_ordered_with<_Tp, _Up>;
394
395// [concepts.object]
396template<class _Tp>
397concept movable =
398  is_object_v<_Tp> &&
399  move_constructible<_Tp> &&
400  assignable_from<_Tp&, _Tp> &&
401  swappable<_Tp>;
402
403template<class _Tp>
404concept copyable =
405  copy_constructible<_Tp> &&
406  movable<_Tp> &&
407  assignable_from<_Tp&, _Tp&> &&
408  assignable_from<_Tp&, const _Tp&> &&
409  assignable_from<_Tp&, const _Tp>;
410
411template<class _Tp>
412concept semiregular = copyable<_Tp> && default_initializable<_Tp>;
413
414template<class _Tp>
415concept regular = semiregular<_Tp> && equality_comparable<_Tp>;
416
417// [concept.invocable]
418template<class _Fn, class... _Args>
419concept invocable = requires(_Fn&& __fn, _Args&&... __args) {
420  _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving
421};
422
423// [concept.regular.invocable]
424template<class _Fn, class... _Args>
425concept regular_invocable = invocable<_Fn, _Args...>;
426
427// [concept.predicate]
428template<class _Fn, class... _Args>
429concept predicate =
430  regular_invocable<_Fn, _Args...> && __boolean_testable<invoke_result_t<_Fn, _Args...>>;
431
432// [concept.relation]
433template<class _Rp, class _Tp, class _Up>
434concept relation =
435  predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> &&
436  predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>;
437
438// [concept.equiv]
439template<class _Rp, class _Tp, class _Up>
440concept equivalence_relation = relation<_Rp, _Tp, _Up>;
441
442// [concept.strictweakorder]
443template<class _Rp, class _Tp, class _Up>
444concept strict_weak_order = relation<_Rp, _Tp, _Up>;
445
446template<class _Tp, class _Up>
447concept __different_from = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
448
449#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
450
451_LIBCPP_END_NAMESPACE_STD
452
453_LIBCPP_POP_MACROS
454
455#endif // _LIBCPP_CONCEPTS
456