// concepts standard header (core) // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef _CONCEPTS_ #define _CONCEPTS_ #include #if _STL_COMPILER_PREPROCESSOR #if !_HAS_CXX20 _EMIT_STL_WARNING(STL4038, "The contents of are available only with C++20 or later."); #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv #include #include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) #pragma warning(disable : _STL_DISABLED_WARNINGS) _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new _STD_BEGIN template concept _Same_impl = // Must be a distinct concept to provide symmetric subsumption for same_as #ifdef __clang__ __is_same(_Ty1, _Ty2); #else // ^^^ use intrinsic / no intrinsic vvv is_same_v<_Ty1, _Ty2>; #endif // ^^^ no intrinsic ^^^ _EXPORT_STD template concept same_as = _Same_impl<_Ty1, _Ty2> && _Same_impl<_Ty2, _Ty1>; _EXPORT_STD template concept derived_from = __is_base_of(_Base, _Derived) && __is_convertible_to(const volatile _Derived*, const volatile _Base*); template concept _Implicitly_convertible_to = is_convertible_v<_From, _To>; _EXPORT_STD template concept common_reference_with = requires { typename common_reference_t<_Ty1, _Ty2>; typename common_reference_t<_Ty2, _Ty1>; } && same_as, common_reference_t<_Ty2, _Ty1>> && convertible_to<_Ty1, common_reference_t<_Ty1, _Ty2>> && convertible_to<_Ty2, common_reference_t<_Ty1, _Ty2>>; // clang-format off _EXPORT_STD template concept common_with = requires { typename common_type_t<_Ty1, _Ty2>; typename common_type_t<_Ty2, _Ty1>; } && same_as, common_type_t<_Ty2, _Ty1>> && requires { static_cast>(_STD declval<_Ty1>()); static_cast>(_STD declval<_Ty2>()); } && common_reference_with, add_lvalue_reference_t> && common_reference_with>, common_reference_t, add_lvalue_reference_t>>; // clang-format on _EXPORT_STD template concept integral = is_integral_v<_Ty>; _EXPORT_STD template concept signed_integral = integral<_Ty> && static_cast<_Ty>(-1) < static_cast<_Ty>(0); _EXPORT_STD template concept unsigned_integral = integral<_Ty> && !signed_integral<_Ty>; _EXPORT_STD template concept floating_point = is_floating_point_v<_Ty>; _EXPORT_STD template concept assignable_from = is_lvalue_reference_v<_LTy> && common_reference_with&, const remove_reference_t<_RTy>&> && requires(_LTy _Left, _RTy&& _Right) { { _Left = static_cast<_RTy&&>(_Right) } -> same_as<_LTy>; }; // swappable and swappable_with are defined below, since they depend on move_constructible. _EXPORT_STD template concept destructible = __is_nothrow_destructible(_Ty); _EXPORT_STD template concept constructible_from = destructible<_Ty> && __is_constructible(_Ty, _ArgTys...); _EXPORT_STD template concept default_initializable = constructible_from<_Ty> && requires { _Ty{}; ::new (static_cast(nullptr)) _Ty; // is-default-initializable<_Ty> }; _EXPORT_STD template concept move_constructible = constructible_from<_Ty, _Ty> && convertible_to<_Ty, _Ty>; template concept _Has_class_or_enum_type = __is_class(remove_reference_t<_Ty>) || __is_enum(remove_reference_t<_Ty>) || __is_union(remove_reference_t<_Ty>); namespace ranges { namespace _Swap { template void swap(_Ty&, _Ty&) = delete; template concept _Use_ADL_swap = (_Has_class_or_enum_type<_Ty1> || _Has_class_or_enum_type<_Ty2>) && requires(_Ty1&& __t, _Ty2&& __u) { swap(static_cast<_Ty1&&>(__t), static_cast<_Ty2&&>(__u)); // intentional ADL }; struct _Cpo { template requires _Use_ADL_swap<_Ty1, _Ty2> _STATIC_CALL_OPERATOR constexpr void operator()(_Ty1&& __t, _Ty2&& __u) _CONST_CALL_OPERATOR noexcept(noexcept(swap(static_cast<_Ty1&&>(__t), static_cast<_Ty2&&>(__u)))) { // intentional ADL swap(static_cast<_Ty1&&>(__t), static_cast<_Ty2&&>(__u)); // intentional ADL } template requires (!_Use_ADL_swap<_Ty&, _Ty&> && move_constructible<_Ty> && assignable_from<_Ty&, _Ty>) _STATIC_CALL_OPERATOR constexpr void operator()(_Ty& __x, _Ty& __y) _CONST_CALL_OPERATOR noexcept(is_nothrow_move_constructible_v<_Ty> && is_nothrow_move_assignable_v<_Ty>) { _Ty __tmp(static_cast<_Ty&&>(__x)); __x = static_cast<_Ty&&>(__y); __y = static_cast<_Ty&&>(__tmp); } template _STATIC_CALL_OPERATOR constexpr void operator()(_Ty1 (&__t)[_Size], _Ty2 (&__u)[_Size]) _CONST_CALL_OPERATOR noexcept(noexcept(operator()(__t[0], __u[0]))) requires requires(_Cpo __fn) { __fn(__t[0], __u[0]); } { if constexpr (is_same_v<_Ty1, _Ty2> && _Is_trivially_swappable_v<_Ty1>) { if (!_STD is_constant_evaluated()) { _STD _Swap_trivial_arrays(__t, __u); return; } } for (size_t __i = 0; __i < _Size; ++__i) { operator()(__t[__i], __u[__i]); } } }; } // namespace _Swap inline namespace _Cpos { _EXPORT_STD inline constexpr _Swap::_Cpo swap; } } // namespace ranges _EXPORT_STD template concept swappable = requires(_Ty& __x, _Ty& __y) { _RANGES swap(__x, __y); }; _EXPORT_STD template concept swappable_with = common_reference_with<_Ty1, _Ty2> && requires(_Ty1&& __t, _Ty2&& __u) { _RANGES swap(static_cast<_Ty1&&>(__t), static_cast<_Ty1&&>(__t)); _RANGES swap(static_cast<_Ty2&&>(__u), static_cast<_Ty2&&>(__u)); _RANGES swap(static_cast<_Ty1&&>(__t), static_cast<_Ty2&&>(__u)); _RANGES swap(static_cast<_Ty2&&>(__u), static_cast<_Ty1&&>(__t)); }; _EXPORT_STD template concept copy_constructible = move_constructible<_Ty> && constructible_from<_Ty, _Ty&> && convertible_to<_Ty&, _Ty> && constructible_from<_Ty, const _Ty&> && convertible_to && constructible_from<_Ty, const _Ty> && convertible_to; template concept _Boolean_testable_impl = convertible_to<_Ty, bool>; template concept _Boolean_testable = _Boolean_testable_impl<_Ty> && requires(_Ty&& __t) { { !static_cast<_Ty&&>(__t) } -> _Boolean_testable_impl; }; template concept _Half_equality_comparable = requires(const remove_reference_t<_Ty1>& __x, const remove_reference_t<_Ty2>& __y) { { __x == __y } -> _Boolean_testable; { __x != __y } -> _Boolean_testable; }; template concept _Weakly_equality_comparable_with = _Half_equality_comparable<_Ty1, _Ty2> && _Half_equality_comparable<_Ty2, _Ty1>; _EXPORT_STD template concept equality_comparable = _Half_equality_comparable<_Ty, _Ty>; #if _HAS_CXX23 template > concept _Comparison_common_type_with_impl = same_as<_Ref, common_reference_t> && requires { requires convertible_to || convertible_to<_Ty1, const _Ref&>; requires convertible_to || convertible_to<_Ty2, const _Ref&>; }; template concept _Comparison_common_type_with = _Comparison_common_type_with_impl, remove_cvref_t<_Ty2>>; #endif // _HAS_CXX23 _EXPORT_STD template concept equality_comparable_with = equality_comparable<_Ty1> && equality_comparable<_Ty2> #if _HAS_CXX23 && _Comparison_common_type_with<_Ty1, _Ty2> #else // ^^^ _HAS_CXX23 / !_HAS_CXX23 vvv && common_reference_with&, const remove_reference_t<_Ty2>&> #endif // ^^^ !_HAS_CXX23 ^^^ && equality_comparable&, const remove_reference_t<_Ty2>&>> && _Weakly_equality_comparable_with<_Ty1, _Ty2>; template concept _Half_ordered = requires(const remove_reference_t<_Ty1>& __t, const remove_reference_t<_Ty2>& __u) { { __t < __u } -> _Boolean_testable; { __t > __u } -> _Boolean_testable; { __t <= __u } -> _Boolean_testable; { __t >= __u } -> _Boolean_testable; }; template concept _Partially_ordered_with = _Half_ordered<_Ty1, _Ty2> && _Half_ordered<_Ty2, _Ty1>; _EXPORT_STD template concept totally_ordered = equality_comparable<_Ty> && _Half_ordered<_Ty, _Ty>; _EXPORT_STD template concept totally_ordered_with = totally_ordered<_Ty1> && totally_ordered<_Ty2> && equality_comparable_with<_Ty1, _Ty2> && totally_ordered&, const remove_reference_t<_Ty2>&>> && _Partially_ordered_with<_Ty1, _Ty2>; _EXPORT_STD template concept movable = is_object_v<_Ty> && move_constructible<_Ty> && assignable_from<_Ty&, _Ty> && swappable<_Ty>; _EXPORT_STD template concept copyable = copy_constructible<_Ty> && movable<_Ty> && assignable_from<_Ty&, _Ty&> && assignable_from<_Ty&, const _Ty&> && assignable_from<_Ty&, const _Ty>; _EXPORT_STD template concept semiregular = copyable<_Ty> && default_initializable<_Ty>; _EXPORT_STD template concept regular = semiregular<_Ty> && equality_comparable<_Ty>; _EXPORT_STD template concept invocable = requires( _FTy&& _Fn, _ArgTys&&... _Args) { _STD invoke(static_cast<_FTy&&>(_Fn), static_cast<_ArgTys&&>(_Args)...); }; _EXPORT_STD template concept regular_invocable = invocable<_FTy, _ArgTys...>; _EXPORT_STD template concept predicate = regular_invocable<_FTy, _ArgTys...> && _Boolean_testable>; _EXPORT_STD template concept relation = predicate<_FTy, _Ty1, _Ty1> && predicate<_FTy, _Ty2, _Ty2> && predicate<_FTy, _Ty1, _Ty2> && predicate<_FTy, _Ty2, _Ty1>; _EXPORT_STD template concept equivalence_relation = relation<_FTy, _Ty1, _Ty2>; _EXPORT_STD template concept strict_weak_order = relation<_FTy, _Ty1, _Ty2>; template struct _Choice_t { _Ty _Strategy = _Ty{}; bool _No_throw = false; }; _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _HAS_CXX20 #endif // _STL_COMPILER_PREPROCESSOR #endif // _CONCEPTS_