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.defaultconstructible], concept default_constructible
71  template<class T>
72    concept default_constructible = 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  // [concepts.compare], comparison concepts
83  // [concept.boolean], concept boolean
84  template<class B>
85    concept boolean = see below;
86
87  // [concept.equalitycomparable], concept equality_comparable
88  template<class T>
89    concept equality_comparable = see below;
90  template<class T, class U>
91    concept equality_comparable_with = see below;
92
93  // [concept.totallyordered], concept totally_ordered
94  template<class T>
95    concept totally_ordered = see below;
96  template<class T, class U>
97    concept totally_ordered_with = see below;
98
99  // [concepts.object], object concepts
100  template<class T>
101    concept movable = see below;
102  template<class T>
103    concept copyable = see below;
104  template<class T>
105    concept semiregular = see below;
106  template<class T>
107    concept regular = see below;
108
109  // [concepts.callable], callable concepts
110  // [concept.invocable], concept invocable
111  template<class F, class... Args>
112    concept invocable = see below;
113
114  // [concept.regularinvocable], concept regular_invocable
115  template<class F, class... Args>
116    concept regular_invocable = see below;
117
118  // [concept.predicate], concept predicate
119  template<class F, class... Args>
120    concept predicate = see below;
121
122  // [concept.relation], concept relation
123  template<class R, class T, class U>
124    concept relation = see below;
125
126  // [concept.equiv], concept equivalence_relation
127  template<class R, class T, class U>
128    concept equivalence_relation = see below;
129
130  // [concept.strictweakorder], concept strict_weak_order
131  template<class R, class T, class U>
132    concept strict_weak_order = see below;
133}
134
135*/
136
137#include <__config>
138#include <functional>
139#include <type_traits>
140#include <utility>
141#include <version>
142
143#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
144#pragma GCC system_header
145#endif
146
147_LIBCPP_PUSH_MACROS
148#include <__undef_macros>
149
150_LIBCPP_BEGIN_NAMESPACE_STD
151
152#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
153
154// [concept.same]
155
156template<class _Tp, class _Up>
157concept __same_as_impl = _VSTD::_IsSame<_Tp, _Up>::value;
158
159template<class _Tp, class _Up>
160concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;
161
162// [concept.derived]
163template<class _Dp, class _Bp>
164concept derived_from =
165  is_base_of_v<_Bp, _Dp> &&
166  is_convertible_v<const volatile _Dp*, const volatile _Bp*>;
167
168// [concept.convertible]
169template<class _From, class _To>
170concept convertible_to =
171  is_convertible_v<_From, _To> &&
172  requires(add_rvalue_reference_t<_From> (&__f)()) {
173    static_cast<_To>(__f());
174  };
175
176// [concept.commonref]
177template<class _Tp, class _Up>
178concept common_reference_with =
179  same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> &&
180  convertible_to<_Tp, common_reference_t<_Tp, _Up>> &&
181  convertible_to<_Up, common_reference_t<_Tp, _Up>>;
182
183// [concept.common]
184template<class _Tp, class _Up>
185concept common_with =
186  same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> &&
187  requires {
188    static_cast<common_type_t<_Tp, _Up>>(_VSTD::declval<_Tp>());
189    static_cast<common_type_t<_Tp, _Up>>(_VSTD::declval<_Up>());
190  } &&
191  common_reference_with<
192    add_lvalue_reference_t<const _Tp>,
193    add_lvalue_reference_t<const _Up>> &&
194  common_reference_with<
195    add_lvalue_reference_t<common_type_t<_Tp, _Up>>,
196    common_reference_t<
197      add_lvalue_reference_t<const _Tp>,
198      add_lvalue_reference_t<const _Up>>>;
199
200// [concepts.arithmetic], arithmetic concepts
201template<class _Tp>
202concept integral = is_integral_v<_Tp>;
203
204template<class _Tp>
205concept signed_integral = integral<_Tp> && is_signed_v<_Tp>;
206
207template<class _Tp>
208concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
209
210template<class _Tp>
211concept floating_point = is_floating_point_v<_Tp>;
212
213// [concept.assignable]
214template<class _Lhs, class _Rhs>
215concept assignable_from =
216  is_lvalue_reference_v<_Lhs> &&
217  common_reference_with<const remove_reference_t<_Lhs>&, const remove_reference_t<_Rhs>&> &&
218  requires (_Lhs __lhs, _Rhs&& __rhs) {
219    { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>;
220  };
221
222// [concept.destructible]
223
224template<class _Tp>
225concept destructible = _VSTD::is_nothrow_destructible_v<_Tp>;
226
227// [concept.constructible]
228template<class _Tp, class... _Args>
229concept constructible_from =
230    destructible<_Tp> && _VSTD::is_constructible_v<_Tp, _Args...>;
231
232// [concept.default.init]
233
234template<class _Tp>
235concept __default_initializable = requires { ::new _Tp; };
236
237template<class _Tp>
238concept default_initializable = constructible_from<_Tp> &&
239    requires { _Tp{}; } && __default_initializable<_Tp>;
240
241// [concept.moveconstructible]
242template<class _Tp>
243concept move_constructible =
244  constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
245
246// [concept.copyconstructible]
247template<class _Tp>
248concept copy_constructible =
249  move_constructible<_Tp> &&
250  constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> &&
251  constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> &&
252  constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _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  template<class _Tp>
261  concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
262
263  // [1]
264  template<class _Tp, class _Up>
265  concept __unqualified_swappable_with =
266    (__class_or_enum<remove_cvref_t<_Tp>> || __class_or_enum<remove_cvref_t<_Up>>) &&
267    requires(_Tp&& __t, _Up&& __u) {
268      swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
269    };
270
271  struct __fn;
272
273  template<class _Tp, class _Up, size_t _Size>
274  concept __swappable_arrays =
275    !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> &&
276    extent_v<_Tp> == extent_v<_Up> &&
277    requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) {
278      __swap(__t[0], __u[0]);
279    };
280
281  template<class _Tp>
282  concept __exchangeable =
283    !__unqualified_swappable_with<_Tp&, _Tp&> &&
284    move_constructible<_Tp> &&
285    assignable_from<_Tp&, _Tp>;
286
287  struct __fn {
288    // 2.1   `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and...
289    // *The name `swap` is used here unqualified.
290    template<class _Tp, class _Up>
291    requires __unqualified_swappable_with<_Tp, _Up>
292    constexpr void operator()(_Tp&& __t, _Up&& __u) const
293    noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))
294    {
295      swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
296    }
297
298    // 2.2   Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and...
299    template<class _Tp, class _Up, size_t _Size>
300    requires __swappable_arrays<_Tp, _Up, _Size>
301    constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const
302    noexcept(noexcept((*this)(*__t, *__u)))
303    {
304      // TODO(cjdb): replace with `ranges::swap_ranges`.
305      for (size_t __i = 0; __i < _Size; ++__i) {
306        (*this)(__t[__i], __u[__i]);
307      }
308    }
309
310    // 2.3   Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models...
311    template<__exchangeable _Tp>
312    constexpr void operator()(_Tp& __x, _Tp& __y) const
313    noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>)
314    {
315      __y = _VSTD::exchange(__x, _VSTD::move(__y));
316    }
317  };
318} // namespace ranges::__swap
319
320namespace ranges::inline __cpo {
321  inline constexpr auto swap = __swap::__fn{};
322} // namespace ranges::__cpo
323
324template<class _Tp>
325concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); };
326
327template<class _Tp, class _Up>
328concept swappable_with =
329  common_reference_with<_Tp&, _Up&> &&
330  requires(_Tp&& __t, _Up&& __u) {
331    ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t));
332    ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u));
333    ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
334    ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t));
335  };
336
337// [concept.booleantestable]
338template<class _Tp>
339concept __boolean_testable_impl = convertible_to<_Tp, bool>;
340
341template<class _Tp>
342concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) {
343  { !std::forward<_Tp>(__t) } -> __boolean_testable_impl;
344};
345
346// [concept.equalitycomparable]
347template<class _Tp, class _Up>
348concept __weakly_equality_comparable_with =
349  requires(const remove_reference_t<_Tp>& __t, const remove_reference_t<_Up>& __u) {
350    { __t == __u } -> __boolean_testable;
351    { __t != __u } -> __boolean_testable;
352    { __u == __t } -> __boolean_testable;
353    { __u != __t } -> __boolean_testable;
354  };
355
356template<class _Tp>
357concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
358
359template<class _Tp, class _Up>
360concept equality_comparable_with =
361  equality_comparable<_Tp> && equality_comparable<_Up> &&
362  common_reference_with<const remove_reference_t<_Tp>&, const remove_reference_t<_Up>&> &&
363  equality_comparable<
364    common_reference_t<
365      const remove_reference_t<_Tp>&,
366      const remove_reference_t<_Up>&>> &&
367  __weakly_equality_comparable_with<_Tp, _Up>;
368
369// [concepts.object]
370template<class _Tp>
371concept movable =
372  is_object_v<_Tp> &&
373  move_constructible<_Tp> &&
374  assignable_from<_Tp&, _Tp> &&
375  swappable<_Tp>;
376
377template<class _Tp>
378concept copyable =
379  copy_constructible<_Tp> &&
380  movable<_Tp> &&
381  assignable_from<_Tp&, _Tp&> &&
382  assignable_from<_Tp&, const _Tp&> &&
383  assignable_from<_Tp&, const _Tp>;
384
385template<class _Tp>
386concept semiregular = copyable<_Tp> && default_initializable<_Tp>;
387
388template<class _Tp>
389concept regular = semiregular<_Tp> && equality_comparable<_Tp>;
390
391// [concept.invocable]
392template<class _Fn, class... _Args>
393concept invocable = requires(_Fn&& __fn, _Args&&... __args) {
394  _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving
395};
396
397// [concept.regular.invocable]
398template<class _Fn, class... _Args>
399concept regular_invocable = invocable<_Fn, _Args...>;
400
401#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
402
403_LIBCPP_END_NAMESPACE_STD
404
405_LIBCPP_POP_MACROS
406
407#endif // _LIBCPP_CONCEPTS
408