xref: /freebsd/contrib/llvm-project/libcxx/include/concepts (revision fe6060f10f634930ff71b7c50291ddc610da2475)
15ffd83dbSDimitry Andric// -*- C++ -*-
25ffd83dbSDimitry Andric//===-------------------------- concepts ----------------------------------===//
35ffd83dbSDimitry Andric//
45ffd83dbSDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
55ffd83dbSDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
65ffd83dbSDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
75ffd83dbSDimitry Andric//
85ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
95ffd83dbSDimitry Andric
105ffd83dbSDimitry Andric#ifndef _LIBCPP_CONCEPTS
115ffd83dbSDimitry Andric#define _LIBCPP_CONCEPTS
125ffd83dbSDimitry Andric
135ffd83dbSDimitry Andric/*
145ffd83dbSDimitry Andric    concepts synopsis
155ffd83dbSDimitry Andricnamespace std {
165ffd83dbSDimitry Andric  // [concepts.lang], language-related concepts
175ffd83dbSDimitry Andric  // [concept.same], concept same_as
185ffd83dbSDimitry Andric  template<class T, class U>
195ffd83dbSDimitry Andric    concept same_as = see below;
205ffd83dbSDimitry Andric
215ffd83dbSDimitry Andric  // [concept.derived], concept derived_from
225ffd83dbSDimitry Andric  template<class Derived, class Base>
235ffd83dbSDimitry Andric    concept derived_from = see below;
245ffd83dbSDimitry Andric
255ffd83dbSDimitry Andric  // [concept.convertible], concept convertible_to
265ffd83dbSDimitry Andric  template<class From, class To>
275ffd83dbSDimitry Andric    concept convertible_to = see below;
285ffd83dbSDimitry Andric
295ffd83dbSDimitry Andric  // [concept.commonref], concept common_reference_with
305ffd83dbSDimitry Andric  template<class T, class U>
315ffd83dbSDimitry Andric    concept common_reference_with = see below;
325ffd83dbSDimitry Andric
335ffd83dbSDimitry Andric  // [concept.common], concept common_with
345ffd83dbSDimitry Andric  template<class T, class U>
355ffd83dbSDimitry Andric    concept common_with = see below;
365ffd83dbSDimitry Andric
375ffd83dbSDimitry Andric  // [concepts.arithmetic], arithmetic concepts
385ffd83dbSDimitry Andric  template<class T>
395ffd83dbSDimitry Andric    concept integral = see below;
405ffd83dbSDimitry Andric  template<class T>
415ffd83dbSDimitry Andric    concept signed_integral = see below;
425ffd83dbSDimitry Andric  template<class T>
435ffd83dbSDimitry Andric    concept unsigned_integral = see below;
445ffd83dbSDimitry Andric  template<class T>
455ffd83dbSDimitry Andric    concept floating_point = see below;
465ffd83dbSDimitry Andric
475ffd83dbSDimitry Andric  // [concept.assignable], concept assignable_from
485ffd83dbSDimitry Andric  template<class LHS, class RHS>
495ffd83dbSDimitry Andric    concept assignable_from = see below;
505ffd83dbSDimitry Andric
515ffd83dbSDimitry Andric  // [concept.swappable], concept swappable
525ffd83dbSDimitry Andric  namespace ranges {
535ffd83dbSDimitry Andric    inline namespace unspecified {
545ffd83dbSDimitry Andric      inline constexpr unspecified swap = unspecified;
555ffd83dbSDimitry Andric    }
565ffd83dbSDimitry Andric  }
575ffd83dbSDimitry Andric  template<class T>
585ffd83dbSDimitry Andric    concept swappable = see below;
595ffd83dbSDimitry Andric  template<class T, class U>
605ffd83dbSDimitry Andric    concept swappable_with = see below;
615ffd83dbSDimitry Andric
625ffd83dbSDimitry Andric  // [concept.destructible], concept destructible
635ffd83dbSDimitry Andric  template<class T>
645ffd83dbSDimitry Andric    concept destructible = see below;
655ffd83dbSDimitry Andric
665ffd83dbSDimitry Andric  // [concept.constructible], concept constructible_from
675ffd83dbSDimitry Andric  template<class T, class... Args>
685ffd83dbSDimitry Andric    concept constructible_from = see below;
695ffd83dbSDimitry Andric
70*fe6060f1SDimitry Andric  // [concept.default.init], concept default_initializable
715ffd83dbSDimitry Andric  template<class T>
72*fe6060f1SDimitry Andric    concept default_initializable = see below;
735ffd83dbSDimitry Andric
745ffd83dbSDimitry Andric  // [concept.moveconstructible], concept move_constructible
755ffd83dbSDimitry Andric  template<class T>
765ffd83dbSDimitry Andric    concept move_constructible = see below;
775ffd83dbSDimitry Andric
785ffd83dbSDimitry Andric  // [concept.copyconstructible], concept copy_constructible
795ffd83dbSDimitry Andric  template<class T>
805ffd83dbSDimitry Andric    concept copy_constructible = see below;
815ffd83dbSDimitry Andric
825ffd83dbSDimitry Andric  // [concept.equalitycomparable], concept equality_comparable
835ffd83dbSDimitry Andric  template<class T>
845ffd83dbSDimitry Andric    concept equality_comparable = see below;
855ffd83dbSDimitry Andric  template<class T, class U>
865ffd83dbSDimitry Andric    concept equality_comparable_with = see below;
875ffd83dbSDimitry Andric
885ffd83dbSDimitry Andric  // [concept.totallyordered], concept totally_ordered
895ffd83dbSDimitry Andric  template<class T>
905ffd83dbSDimitry Andric    concept totally_ordered = see below;
915ffd83dbSDimitry Andric  template<class T, class U>
925ffd83dbSDimitry Andric    concept totally_ordered_with = see below;
935ffd83dbSDimitry Andric
945ffd83dbSDimitry Andric  // [concepts.object], object concepts
955ffd83dbSDimitry Andric  template<class T>
965ffd83dbSDimitry Andric    concept movable = see below;
975ffd83dbSDimitry Andric  template<class T>
985ffd83dbSDimitry Andric    concept copyable = see below;
995ffd83dbSDimitry Andric  template<class T>
1005ffd83dbSDimitry Andric    concept semiregular = see below;
1015ffd83dbSDimitry Andric  template<class T>
1025ffd83dbSDimitry Andric    concept regular = see below;
1035ffd83dbSDimitry Andric
1045ffd83dbSDimitry Andric  // [concepts.callable], callable concepts
1055ffd83dbSDimitry Andric  // [concept.invocable], concept invocable
1065ffd83dbSDimitry Andric  template<class F, class... Args>
1075ffd83dbSDimitry Andric    concept invocable = see below;
1085ffd83dbSDimitry Andric
1095ffd83dbSDimitry Andric  // [concept.regularinvocable], concept regular_invocable
1105ffd83dbSDimitry Andric  template<class F, class... Args>
1115ffd83dbSDimitry Andric    concept regular_invocable = see below;
1125ffd83dbSDimitry Andric
1135ffd83dbSDimitry Andric  // [concept.predicate], concept predicate
1145ffd83dbSDimitry Andric  template<class F, class... Args>
1155ffd83dbSDimitry Andric    concept predicate = see below;
1165ffd83dbSDimitry Andric
1175ffd83dbSDimitry Andric  // [concept.relation], concept relation
1185ffd83dbSDimitry Andric  template<class R, class T, class U>
1195ffd83dbSDimitry Andric    concept relation = see below;
1205ffd83dbSDimitry Andric
1215ffd83dbSDimitry Andric  // [concept.equiv], concept equivalence_relation
1225ffd83dbSDimitry Andric  template<class R, class T, class U>
1235ffd83dbSDimitry Andric    concept equivalence_relation = see below;
1245ffd83dbSDimitry Andric
1255ffd83dbSDimitry Andric  // [concept.strictweakorder], concept strict_weak_order
1265ffd83dbSDimitry Andric  template<class R, class T, class U>
1275ffd83dbSDimitry Andric    concept strict_weak_order = see below;
1285ffd83dbSDimitry Andric}
1295ffd83dbSDimitry Andric
1305ffd83dbSDimitry Andric*/
1315ffd83dbSDimitry Andric
1325ffd83dbSDimitry Andric#include <__config>
133*fe6060f1SDimitry Andric#include <__functional/invoke.h>
134*fe6060f1SDimitry Andric#include <__functional_base>
1355ffd83dbSDimitry Andric#include <type_traits>
136*fe6060f1SDimitry Andric#include <utility>
1375ffd83dbSDimitry Andric#include <version>
1385ffd83dbSDimitry Andric
1395ffd83dbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1405ffd83dbSDimitry Andric#pragma GCC system_header
1415ffd83dbSDimitry Andric#endif
1425ffd83dbSDimitry Andric
1435ffd83dbSDimitry Andric_LIBCPP_PUSH_MACROS
1445ffd83dbSDimitry Andric#include <__undef_macros>
1455ffd83dbSDimitry Andric
1465ffd83dbSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
1475ffd83dbSDimitry Andric
148*fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
1495ffd83dbSDimitry Andric
1505ffd83dbSDimitry Andric// [concept.same]
1515ffd83dbSDimitry Andric
1525ffd83dbSDimitry Andrictemplate<class _Tp, class _Up>
1535ffd83dbSDimitry Andricconcept __same_as_impl = _VSTD::_IsSame<_Tp, _Up>::value;
1545ffd83dbSDimitry Andric
1555ffd83dbSDimitry Andrictemplate<class _Tp, class _Up>
1565ffd83dbSDimitry Andricconcept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;
1575ffd83dbSDimitry Andric
158*fe6060f1SDimitry Andric// [concept.derived]
159*fe6060f1SDimitry Andrictemplate<class _Dp, class _Bp>
160*fe6060f1SDimitry Andricconcept derived_from =
161*fe6060f1SDimitry Andric  is_base_of_v<_Bp, _Dp> &&
162*fe6060f1SDimitry Andric  is_convertible_v<const volatile _Dp*, const volatile _Bp*>;
163*fe6060f1SDimitry Andric
164*fe6060f1SDimitry Andric// [concept.convertible]
165*fe6060f1SDimitry Andrictemplate<class _From, class _To>
166*fe6060f1SDimitry Andricconcept convertible_to =
167*fe6060f1SDimitry Andric  is_convertible_v<_From, _To> &&
168*fe6060f1SDimitry Andric  requires(add_rvalue_reference_t<_From> (&__f)()) {
169*fe6060f1SDimitry Andric    static_cast<_To>(__f());
170*fe6060f1SDimitry Andric  };
171*fe6060f1SDimitry Andric
172*fe6060f1SDimitry Andric// [concept.commonref]
173*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
174*fe6060f1SDimitry Andricconcept common_reference_with =
175*fe6060f1SDimitry Andric  same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> &&
176*fe6060f1SDimitry Andric  convertible_to<_Tp, common_reference_t<_Tp, _Up>> &&
177*fe6060f1SDimitry Andric  convertible_to<_Up, common_reference_t<_Tp, _Up>>;
178*fe6060f1SDimitry Andric
179*fe6060f1SDimitry Andric// [concept.common]
180*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
181*fe6060f1SDimitry Andricconcept common_with =
182*fe6060f1SDimitry Andric  same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> &&
183*fe6060f1SDimitry Andric  requires {
184*fe6060f1SDimitry Andric    static_cast<common_type_t<_Tp, _Up>>(declval<_Tp>());
185*fe6060f1SDimitry Andric    static_cast<common_type_t<_Tp, _Up>>(declval<_Up>());
186*fe6060f1SDimitry Andric  } &&
187*fe6060f1SDimitry Andric  common_reference_with<
188*fe6060f1SDimitry Andric    add_lvalue_reference_t<const _Tp>,
189*fe6060f1SDimitry Andric    add_lvalue_reference_t<const _Up>> &&
190*fe6060f1SDimitry Andric  common_reference_with<
191*fe6060f1SDimitry Andric    add_lvalue_reference_t<common_type_t<_Tp, _Up>>,
192*fe6060f1SDimitry Andric    common_reference_t<
193*fe6060f1SDimitry Andric      add_lvalue_reference_t<const _Tp>,
194*fe6060f1SDimitry Andric      add_lvalue_reference_t<const _Up>>>;
195*fe6060f1SDimitry Andric
196*fe6060f1SDimitry Andric// [concepts.arithmetic], arithmetic concepts
197*fe6060f1SDimitry Andrictemplate<class _Tp>
198*fe6060f1SDimitry Andricconcept integral = is_integral_v<_Tp>;
199*fe6060f1SDimitry Andric
200*fe6060f1SDimitry Andrictemplate<class _Tp>
201*fe6060f1SDimitry Andricconcept signed_integral = integral<_Tp> && is_signed_v<_Tp>;
202*fe6060f1SDimitry Andric
203*fe6060f1SDimitry Andrictemplate<class _Tp>
204*fe6060f1SDimitry Andricconcept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
205*fe6060f1SDimitry Andric
206*fe6060f1SDimitry Andrictemplate<class _Tp>
207*fe6060f1SDimitry Andricconcept floating_point = is_floating_point_v<_Tp>;
208*fe6060f1SDimitry Andric
209*fe6060f1SDimitry Andric// [concept.assignable]
210*fe6060f1SDimitry Andrictemplate<class _Lhs, class _Rhs>
211*fe6060f1SDimitry Andricconcept assignable_from =
212*fe6060f1SDimitry Andric  is_lvalue_reference_v<_Lhs> &&
213*fe6060f1SDimitry Andric  common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> &&
214*fe6060f1SDimitry Andric  requires (_Lhs __lhs, _Rhs&& __rhs) {
215*fe6060f1SDimitry Andric    { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>;
216*fe6060f1SDimitry Andric  };
217*fe6060f1SDimitry Andric
218e8d8bef9SDimitry Andric// [concept.destructible]
219e8d8bef9SDimitry Andric
220e8d8bef9SDimitry Andrictemplate<class _Tp>
221*fe6060f1SDimitry Andricconcept destructible = is_nothrow_destructible_v<_Tp>;
222e8d8bef9SDimitry Andric
223*fe6060f1SDimitry Andric// [concept.constructible]
224*fe6060f1SDimitry Andrictemplate<class _Tp, class... _Args>
225*fe6060f1SDimitry Andricconcept constructible_from =
226*fe6060f1SDimitry Andric    destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
227*fe6060f1SDimitry Andric
228*fe6060f1SDimitry Andric// [concept.default.init]
229*fe6060f1SDimitry Andric
230*fe6060f1SDimitry Andrictemplate<class _Tp>
231*fe6060f1SDimitry Andricconcept __default_initializable = requires { ::new _Tp; };
232*fe6060f1SDimitry Andric
233*fe6060f1SDimitry Andrictemplate<class _Tp>
234*fe6060f1SDimitry Andricconcept default_initializable = constructible_from<_Tp> &&
235*fe6060f1SDimitry Andric    requires { _Tp{}; } && __default_initializable<_Tp>;
236*fe6060f1SDimitry Andric
237*fe6060f1SDimitry Andric// [concept.moveconstructible]
238*fe6060f1SDimitry Andrictemplate<class _Tp>
239*fe6060f1SDimitry Andricconcept move_constructible =
240*fe6060f1SDimitry Andric  constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;
241*fe6060f1SDimitry Andric
242*fe6060f1SDimitry Andric// [concept.copyconstructible]
243*fe6060f1SDimitry Andrictemplate<class _Tp>
244*fe6060f1SDimitry Andricconcept copy_constructible =
245*fe6060f1SDimitry Andric  move_constructible<_Tp> &&
246*fe6060f1SDimitry Andric  constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> &&
247*fe6060f1SDimitry Andric  constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> &&
248*fe6060f1SDimitry Andric  constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>;
249*fe6060f1SDimitry Andric
250*fe6060f1SDimitry Andric// Whether a type is a class type or enumeration type according to the Core wording.
251*fe6060f1SDimitry Andrictemplate<class _Tp>
252*fe6060f1SDimitry Andricconcept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
253*fe6060f1SDimitry Andric
254*fe6060f1SDimitry Andric// [concept.swappable]
255*fe6060f1SDimitry Andricnamespace ranges::__swap {
256*fe6060f1SDimitry Andric  // Deleted to inhibit ADL
257*fe6060f1SDimitry Andric  template<class _Tp>
258*fe6060f1SDimitry Andric  void swap(_Tp&, _Tp&) = delete;
259*fe6060f1SDimitry Andric
260*fe6060f1SDimitry Andric
261*fe6060f1SDimitry Andric  // [1]
262*fe6060f1SDimitry Andric  template<class _Tp, class _Up>
263*fe6060f1SDimitry Andric  concept __unqualified_swappable_with =
264*fe6060f1SDimitry Andric    (__class_or_enum<remove_cvref_t<_Tp>> || __class_or_enum<remove_cvref_t<_Up>>) &&
265*fe6060f1SDimitry Andric    requires(_Tp&& __t, _Up&& __u) {
266*fe6060f1SDimitry Andric      swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
267*fe6060f1SDimitry Andric    };
268*fe6060f1SDimitry Andric
269*fe6060f1SDimitry Andric  struct __fn;
270*fe6060f1SDimitry Andric
271*fe6060f1SDimitry Andric  template<class _Tp, class _Up, size_t _Size>
272*fe6060f1SDimitry Andric  concept __swappable_arrays =
273*fe6060f1SDimitry Andric    !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> &&
274*fe6060f1SDimitry Andric    extent_v<_Tp> == extent_v<_Up> &&
275*fe6060f1SDimitry Andric    requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) {
276*fe6060f1SDimitry Andric      __swap(__t[0], __u[0]);
277*fe6060f1SDimitry Andric    };
278*fe6060f1SDimitry Andric
279*fe6060f1SDimitry Andric  template<class _Tp>
280*fe6060f1SDimitry Andric  concept __exchangeable =
281*fe6060f1SDimitry Andric    !__unqualified_swappable_with<_Tp&, _Tp&> &&
282*fe6060f1SDimitry Andric    move_constructible<_Tp> &&
283*fe6060f1SDimitry Andric    assignable_from<_Tp&, _Tp>;
284*fe6060f1SDimitry Andric
285*fe6060f1SDimitry Andric  struct __fn {
286*fe6060f1SDimitry Andric    // 2.1   `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and...
287*fe6060f1SDimitry Andric    // *The name `swap` is used here unqualified.
288*fe6060f1SDimitry Andric    template<class _Tp, class _Up>
289*fe6060f1SDimitry Andric    requires __unqualified_swappable_with<_Tp, _Up>
290*fe6060f1SDimitry Andric    constexpr void operator()(_Tp&& __t, _Up&& __u) const
291*fe6060f1SDimitry Andric    noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u))))
292*fe6060f1SDimitry Andric    {
293*fe6060f1SDimitry Andric      swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
294*fe6060f1SDimitry Andric    }
295*fe6060f1SDimitry Andric
296*fe6060f1SDimitry Andric    // 2.2   Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and...
297*fe6060f1SDimitry Andric    template<class _Tp, class _Up, size_t _Size>
298*fe6060f1SDimitry Andric    requires __swappable_arrays<_Tp, _Up, _Size>
299*fe6060f1SDimitry Andric    constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const
300*fe6060f1SDimitry Andric    noexcept(noexcept((*this)(*__t, *__u)))
301*fe6060f1SDimitry Andric    {
302*fe6060f1SDimitry Andric      // TODO(cjdb): replace with `ranges::swap_ranges`.
303*fe6060f1SDimitry Andric      for (size_t __i = 0; __i < _Size; ++__i) {
304*fe6060f1SDimitry Andric        (*this)(__t[__i], __u[__i]);
305*fe6060f1SDimitry Andric      }
306*fe6060f1SDimitry Andric    }
307*fe6060f1SDimitry Andric
308*fe6060f1SDimitry Andric    // 2.3   Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models...
309*fe6060f1SDimitry Andric    template<__exchangeable _Tp>
310*fe6060f1SDimitry Andric    constexpr void operator()(_Tp& __x, _Tp& __y) const
311*fe6060f1SDimitry Andric    noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>)
312*fe6060f1SDimitry Andric    {
313*fe6060f1SDimitry Andric      __y = _VSTD::exchange(__x, _VSTD::move(__y));
314*fe6060f1SDimitry Andric    }
315*fe6060f1SDimitry Andric  };
316*fe6060f1SDimitry Andric} // namespace ranges::__swap
317*fe6060f1SDimitry Andric
318*fe6060f1SDimitry Andricnamespace ranges::inline __cpo {
319*fe6060f1SDimitry Andric  inline constexpr auto swap = __swap::__fn{};
320*fe6060f1SDimitry Andric} // namespace ranges::__cpo
321*fe6060f1SDimitry Andric
322*fe6060f1SDimitry Andrictemplate<class _Tp>
323*fe6060f1SDimitry Andricconcept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); };
324*fe6060f1SDimitry Andric
325*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
326*fe6060f1SDimitry Andricconcept swappable_with =
327*fe6060f1SDimitry Andric  common_reference_with<_Tp, _Up> &&
328*fe6060f1SDimitry Andric  requires(_Tp&& __t, _Up&& __u) {
329*fe6060f1SDimitry Andric    ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t));
330*fe6060f1SDimitry Andric    ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u));
331*fe6060f1SDimitry Andric    ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u));
332*fe6060f1SDimitry Andric    ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t));
333*fe6060f1SDimitry Andric  };
334*fe6060f1SDimitry Andric
335*fe6060f1SDimitry Andric// [concept.booleantestable]
336*fe6060f1SDimitry Andrictemplate<class _Tp>
337*fe6060f1SDimitry Andricconcept __boolean_testable_impl = convertible_to<_Tp, bool>;
338*fe6060f1SDimitry Andric
339*fe6060f1SDimitry Andrictemplate<class _Tp>
340*fe6060f1SDimitry Andricconcept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) {
341*fe6060f1SDimitry Andric  { !std::forward<_Tp>(__t) } -> __boolean_testable_impl;
342*fe6060f1SDimitry Andric};
343*fe6060f1SDimitry Andric
344*fe6060f1SDimitry Andric// [concept.equalitycomparable]
345*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
346*fe6060f1SDimitry Andricconcept __weakly_equality_comparable_with =
347*fe6060f1SDimitry Andric  requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
348*fe6060f1SDimitry Andric    { __t == __u } -> __boolean_testable;
349*fe6060f1SDimitry Andric    { __t != __u } -> __boolean_testable;
350*fe6060f1SDimitry Andric    { __u == __t } -> __boolean_testable;
351*fe6060f1SDimitry Andric    { __u != __t } -> __boolean_testable;
352*fe6060f1SDimitry Andric  };
353*fe6060f1SDimitry Andric
354*fe6060f1SDimitry Andrictemplate<class _Tp>
355*fe6060f1SDimitry Andricconcept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
356*fe6060f1SDimitry Andric
357*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
358*fe6060f1SDimitry Andricconcept equality_comparable_with =
359*fe6060f1SDimitry Andric  equality_comparable<_Tp> && equality_comparable<_Up> &&
360*fe6060f1SDimitry Andric  common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
361*fe6060f1SDimitry Andric  equality_comparable<
362*fe6060f1SDimitry Andric    common_reference_t<
363*fe6060f1SDimitry Andric      __make_const_lvalue_ref<_Tp>,
364*fe6060f1SDimitry Andric      __make_const_lvalue_ref<_Up>>> &&
365*fe6060f1SDimitry Andric  __weakly_equality_comparable_with<_Tp, _Up>;
366*fe6060f1SDimitry Andric
367*fe6060f1SDimitry Andric// [concept.totallyordered]
368*fe6060f1SDimitry Andric
369*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
370*fe6060f1SDimitry Andricconcept __partially_ordered_with =
371*fe6060f1SDimitry Andric  requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
372*fe6060f1SDimitry Andric    { __t <  __u } -> __boolean_testable;
373*fe6060f1SDimitry Andric    { __t >  __u } -> __boolean_testable;
374*fe6060f1SDimitry Andric    { __t <= __u } -> __boolean_testable;
375*fe6060f1SDimitry Andric    { __t >= __u } -> __boolean_testable;
376*fe6060f1SDimitry Andric    { __u <  __t } -> __boolean_testable;
377*fe6060f1SDimitry Andric    { __u >  __t } -> __boolean_testable;
378*fe6060f1SDimitry Andric    { __u <= __t } -> __boolean_testable;
379*fe6060f1SDimitry Andric    { __u >= __t } -> __boolean_testable;
380*fe6060f1SDimitry Andric  };
381*fe6060f1SDimitry Andric
382*fe6060f1SDimitry Andrictemplate<class _Tp>
383*fe6060f1SDimitry Andricconcept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>;
384*fe6060f1SDimitry Andric
385*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
386*fe6060f1SDimitry Andricconcept totally_ordered_with =
387*fe6060f1SDimitry Andric  totally_ordered<_Tp> && totally_ordered<_Up> &&
388*fe6060f1SDimitry Andric  equality_comparable_with<_Tp, _Up> &&
389*fe6060f1SDimitry Andric  totally_ordered<
390*fe6060f1SDimitry Andric    common_reference_t<
391*fe6060f1SDimitry Andric      __make_const_lvalue_ref<_Tp>,
392*fe6060f1SDimitry Andric      __make_const_lvalue_ref<_Up>>> &&
393*fe6060f1SDimitry Andric  __partially_ordered_with<_Tp, _Up>;
394*fe6060f1SDimitry Andric
395*fe6060f1SDimitry Andric// [concepts.object]
396*fe6060f1SDimitry Andrictemplate<class _Tp>
397*fe6060f1SDimitry Andricconcept movable =
398*fe6060f1SDimitry Andric  is_object_v<_Tp> &&
399*fe6060f1SDimitry Andric  move_constructible<_Tp> &&
400*fe6060f1SDimitry Andric  assignable_from<_Tp&, _Tp> &&
401*fe6060f1SDimitry Andric  swappable<_Tp>;
402*fe6060f1SDimitry Andric
403*fe6060f1SDimitry Andrictemplate<class _Tp>
404*fe6060f1SDimitry Andricconcept copyable =
405*fe6060f1SDimitry Andric  copy_constructible<_Tp> &&
406*fe6060f1SDimitry Andric  movable<_Tp> &&
407*fe6060f1SDimitry Andric  assignable_from<_Tp&, _Tp&> &&
408*fe6060f1SDimitry Andric  assignable_from<_Tp&, const _Tp&> &&
409*fe6060f1SDimitry Andric  assignable_from<_Tp&, const _Tp>;
410*fe6060f1SDimitry Andric
411*fe6060f1SDimitry Andrictemplate<class _Tp>
412*fe6060f1SDimitry Andricconcept semiregular = copyable<_Tp> && default_initializable<_Tp>;
413*fe6060f1SDimitry Andric
414*fe6060f1SDimitry Andrictemplate<class _Tp>
415*fe6060f1SDimitry Andricconcept regular = semiregular<_Tp> && equality_comparable<_Tp>;
416*fe6060f1SDimitry Andric
417*fe6060f1SDimitry Andric// [concept.invocable]
418*fe6060f1SDimitry Andrictemplate<class _Fn, class... _Args>
419*fe6060f1SDimitry Andricconcept invocable = requires(_Fn&& __fn, _Args&&... __args) {
420*fe6060f1SDimitry Andric  _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving
421*fe6060f1SDimitry Andric};
422*fe6060f1SDimitry Andric
423*fe6060f1SDimitry Andric// [concept.regular.invocable]
424*fe6060f1SDimitry Andrictemplate<class _Fn, class... _Args>
425*fe6060f1SDimitry Andricconcept regular_invocable = invocable<_Fn, _Args...>;
426*fe6060f1SDimitry Andric
427*fe6060f1SDimitry Andric// [concept.predicate]
428*fe6060f1SDimitry Andrictemplate<class _Fn, class... _Args>
429*fe6060f1SDimitry Andricconcept predicate =
430*fe6060f1SDimitry Andric  regular_invocable<_Fn, _Args...> && __boolean_testable<invoke_result_t<_Fn, _Args...>>;
431*fe6060f1SDimitry Andric
432*fe6060f1SDimitry Andric// [concept.relation]
433*fe6060f1SDimitry Andrictemplate<class _Rp, class _Tp, class _Up>
434*fe6060f1SDimitry Andricconcept relation =
435*fe6060f1SDimitry Andric  predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> &&
436*fe6060f1SDimitry Andric  predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>;
437*fe6060f1SDimitry Andric
438*fe6060f1SDimitry Andric// [concept.equiv]
439*fe6060f1SDimitry Andrictemplate<class _Rp, class _Tp, class _Up>
440*fe6060f1SDimitry Andricconcept equivalence_relation = relation<_Rp, _Tp, _Up>;
441*fe6060f1SDimitry Andric
442*fe6060f1SDimitry Andric// [concept.strictweakorder]
443*fe6060f1SDimitry Andrictemplate<class _Rp, class _Tp, class _Up>
444*fe6060f1SDimitry Andricconcept strict_weak_order = relation<_Rp, _Tp, _Up>;
445*fe6060f1SDimitry Andric
446*fe6060f1SDimitry Andrictemplate<class _Tp, class _Up>
447*fe6060f1SDimitry Andricconcept __different_from = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
448*fe6060f1SDimitry Andric
449*fe6060f1SDimitry Andric#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
4505ffd83dbSDimitry Andric
4515ffd83dbSDimitry Andric_LIBCPP_END_NAMESPACE_STD
4525ffd83dbSDimitry Andric
4535ffd83dbSDimitry Andric_LIBCPP_POP_MACROS
4545ffd83dbSDimitry Andric
4555ffd83dbSDimitry Andric#endif // _LIBCPP_CONCEPTS
456