diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -97,8 +97,18 @@ __bits __bsd_locale_defaults.h __bsd_locale_fallbacks.h + __compare/cmp_alg.h __compare/common_comparison_category.h + __compare/compare_three_way.h + __compare/compare_three_way_result.h __compare/ordering.h + __compare/three_way_comparable.h + __concepts/__boolean_testable.h + __concepts/common_reference_with.h + __concepts/convertible_to.h + __concepts/equality_comparable.h + __concepts/same_as.h + __concepts/totally_ordered.h __config __debug __errc @@ -233,6 +243,7 @@ __tuple __undef_macros __utility/__decay_copy.h + __utility/__priority_tag.h __utility/as_const.h __utility/cmp.h __utility/declval.h diff --git a/libcxx/include/__compare/cmp_alg.h b/libcxx/include/__compare/cmp_alg.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__compare/cmp_alg.h @@ -0,0 +1,103 @@ +// -*- C++ -*- +//===-------------------------- compare -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_CMP_ALG +#define _LIBCPP___COMPARE_CMP_ALG + +#include <__config> +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__utility/__priority_tag.h> +#include +#include + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +// [cmp.alg] +namespace __strong_order { + struct __fn { + template + requires is_same_v, decay_t<_Fp>> + _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering go(_Ep&& __e, _Fp&& __f, _PriorityTag<2>) + noexcept(noexcept(strong_ordering(strong_order(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f))))) + requires requires { strong_ordering(strong_order(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f))); } + { + return strong_ordering(strong_order(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f))); + } + + template> + requires is_same_v<_Dp, decay_t<_Fp>> && is_floating_point_v<_Dp> + _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering go(_Ep&& __e, _Fp&& __f, _PriorityTag<1>) + noexcept + { + if (__e < __f) { + return strong_ordering::less; + } else if (__e > __f) { + return strong_ordering::greater; + } else if (__e == __f) { + if (__e == 0) { + return _VSTD::signbit(__f) <=> _VSTD::signbit(__e); + } else if (_VSTD::isinf(__e)) { + return strong_ordering::equal; + } else { + int __eexp, __fexp; + (void)_VSTD::frexp(__e, __eexp); + (void)_VSTD::frexp(__f, __fexp); + return (__e < 0) ? (__eexp <=> __fexp) : (__fexp <=> __eexp); + } + } else { + // The order is -QNAN, -SNAN, numbers, +SNAN, +QNAN. + if (_VSTD::isnan(__e)) { + if (_VSTD::isnan(__f)) { + // These two NaNs should be ordered by their payload bits, + // but there's no way to get at that information portably. + return _VSTD::signbit(__f) <=> _VSTD::signbit(__e); + } else { + return _VSTD::signbit(__e) ? strong_ordering::less : strong_ordering::greater; + } + } else { + return _VSTD::signbit(__f) ? strong_ordering::greater : strong_ordering::less; + } + } + } + + template + requires is_same_v, decay_t<_Fp>> + _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering go(_Ep&& __e, _Fp&& __f, _PriorityTag<0>) + noexcept(noexcept(strong_ordering(compare_three_way()(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f))))) + requires requires { strong_ordering(compare_three_way()(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f))); } + { + return strong_ordering(compare_three_way()(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f))); + } + + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ep&& __e, _Fp&& __f) + noexcept(noexcept(__go(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f)))) + -> decltype(__go(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f), _PriorityTag<2>())) + { + return __go(_VSTD::forward<_Ep>(__e), _VSTD::forward<_Fp>(__f), _PriorityTag<2>()); + } + }; +} // namespace __strong_order + +inline namespace __cpo { + inline constexpr auto strong_order = __strong_order::__fn{}; +} // namespace __cpo + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_CMP_ALG diff --git a/libcxx/include/__compare/compare_three_way.h b/libcxx/include/__compare/compare_three_way.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__compare/compare_three_way.h @@ -0,0 +1,41 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_THREE_WAY_H +#define _LIBCPP___COMPARE_COMPARE_THREE_WAY_H + +#include <__config> +#include <__compare/three_way_comparable.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +struct _LIBCPP_TEMPLATE_VIS compare_three_way +{ + template + requires three_way_comparable_with<_T1, _T2> + constexpr _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + noexcept(noexcept(_VSTD::forward<_T1>(__t) <=> _VSTD::forward<_T2>(__u))) + { return _VSTD::forward<_T1>(__t) <=> _VSTD::forward<_T2>(__u); } + + using is_transparent = void; +}; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_H diff --git a/libcxx/include/__compare/compare_three_way_result.h b/libcxx/include/__compare/compare_three_way_result.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__compare/compare_three_way_result.h @@ -0,0 +1,44 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H +#define _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result { }; + +template +struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result<_Tp, _Up, decltype( + declval&>() <=> declval&>(), void() +)> { + using type = decltype(declval&>() <=> declval&>()); +}; + +template +struct _LIBCPP_TEMPLATE_VIS compare_three_way_result : __compare_three_way_result<_Tp, _Up, void> { }; + +template +using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_RESULT_H diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__compare/three_way_comparable.h @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H +#define _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H + +#include <__compare/common_comparison_category.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/same_as.h> +#include <__concepts/totally_ordered.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +template +concept __compares_as = + same_as, _Cat>; + +template +concept three_way_comparable = + __weakly_equality_comparable_with<_Tp, _Tp> && + __partially_ordered_with<_Tp, _Tp> && + requires (const remove_reference_t<_Tp>& __t) { + { __t <=> __t } -> __compares_as<_Cat>; + }; + +template +concept three_way_comparable_with = + three_way_comparable<_Tp, _Cat> && + three_way_comparable<_Up, _Cat> && + common_reference_with&, const remove_reference_t<_Up>&> && + three_way_comparable&, const remove_reference_t<_Up>&>, _Cat> && + __weakly_equality_comparable_with<_Tp, _Up> && + __partially_ordered_with<_Tp, _Up> && + requires (const remove_reference_t<_Tp>& __t, const remove_reference_t<_Up>& __u) { + { __t <=> __u } -> __compares_as<_Cat>; + { __u <=> __t } -> __compares_as<_Cat>; + }; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H diff --git a/libcxx/include/__concepts/__boolean_testable.h b/libcxx/include/__concepts/__boolean_testable.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/__boolean_testable.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE +#define _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE + +#include <__concepts/convertible_to.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concepts.booleantestable] + +template +concept __boolean_testable_impl = convertible_to<_Tp, bool>; + +template +concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { + { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; +}; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_BOOLEAN_TESTABLE diff --git a/libcxx/include/__concepts/common_reference_with.h b/libcxx/include/__concepts/common_reference_with.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/common_reference_with.h @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H +#define _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H + +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.commonref] + +template +concept common_reference_with = + same_as, common_reference_t<_Up, _Tp>> && + convertible_to<_Tp, common_reference_t<_Tp, _Up>> && + convertible_to<_Up, common_reference_t<_Tp, _Up>>; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_COMMON_REFERENCE_WITH_H diff --git a/libcxx/include/__concepts/convertible_to.h b/libcxx/include/__concepts/convertible_to.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/convertible_to.h @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_CONVERTIBLE_TO +#define _LIBCPP___CONCEPTS_CONVERTIBLE_TO + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.convertible] + +template +concept convertible_to = + is_convertible_v<_From, _To> && + requires (add_rvalue_reference_t<_From> (&__f)()) { + static_cast<_To>(__f()); + }; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_CONVERTIBLE_TO diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/equality_comparable.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE +#define _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE + +#include <__concepts/__boolean_testable.h> +#include <__concepts/common_reference_with.h> +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.equalitycomparable] + +template +concept __weakly_equality_comparable_with = + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + +template +concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; + +template +concept equality_comparable_with = + equality_comparable<_Tp> && equality_comparable<_Up> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + equality_comparable< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __weakly_equality_comparable_with<_Tp, _Up>; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_EQUALITY_COMPARABLE diff --git a/libcxx/include/__concepts/same_as.h b/libcxx/include/__concepts/same_as.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/same_as.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_SAME_AS +#define _LIBCPP___CONCEPTS_SAME_AS + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.same] + +template +concept __same_as_impl = _VSTD::_IsSame<_Tp, _Up>::value; + +template +concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_SAME_AS diff --git a/libcxx/include/__concepts/totally_ordered.h b/libcxx/include/__concepts/totally_ordered.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__concepts/totally_ordered.h @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONCEPTS_TOTALLY_ORDERED +#define _LIBCPP___CONCEPTS_TOTALLY_ORDERED + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +// [concept.totallyordered] + +template +concept __partially_ordered_with = + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; + }; + +template +concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; + +template +concept totally_ordered_with = + totally_ordered<_Tp> && totally_ordered<_Up> && + equality_comparable_with<_Tp, _Up> && + totally_ordered< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __partially_ordered_with<_Tp, _Up>; + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CONCEPTS_TOTALLY_ORDERED diff --git a/libcxx/include/__utility/__priority_tag.h b/libcxx/include/__utility/__priority_tag.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__utility/__priority_tag.h @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___UTILITY_PRIORITY_TAG_H +#define _LIBCPP___UTILITY_PRIORITY_TAG_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template struct _PriorityTag : _PriorityTag<_Ip - 1> {}; +template<> struct _PriorityTag<0> {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_PRIORITY_TAG_H diff --git a/libcxx/include/compare b/libcxx/include/compare --- a/libcxx/include/compare +++ b/libcxx/include/compare @@ -35,6 +35,21 @@ template using common_comparison_category_t = typename common_comparison_category::type; + // [cmp.concept], concept three_way_comparable + template + concept three_way_comparable = see below; + template + concept three_way_comparable_with = see below; + + // [cmp.result], result of three-way comparison + template struct compare_three_way_result; + + template + using compare_three_way_result_t = typename compare_three_way_result::type; + + // [comparisons.three.way], class compare_three_way + struct compare_three_way; + // [cmp.alg], comparison algorithms template constexpr strong_ordering strong_order(const T& a, const T& b); template constexpr weak_ordering weak_order(const T& a, const T& b); @@ -120,27 +135,13 @@ } */ +#include <__compare/cmp_alg.h> #include <__compare/common_comparison_category.h> +#include <__compare/compare_three_way.h> +#include <__compare/compare_three_way_result.h> #include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> #include <__config> #include -#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -#pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) - -// [cmp.alg], comparison algorithms -// TODO: unimplemented -template constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs); -template constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs); -template constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs); - -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) - -_LIBCPP_END_NAMESPACE_STD - #endif // _LIBCPP_COMPARE diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -1,5 +1,4 @@ -// -*- C++ -*- -//===-------------------------- concepts ----------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -129,6 +128,12 @@ */ +#include <__concepts/__boolean_testable.h> +#include <__concepts/common_reference_with.h> +#include <__concepts/convertible_to.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/same_as.h> +#include <__concepts/totally_ordered.h> #include <__config> #include <__functional/invoke.h> #include <__functional_base> @@ -147,35 +152,12 @@ #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS) -// [concept.same] - -template -concept __same_as_impl = _VSTD::_IsSame<_Tp, _Up>::value; - -template -concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; - // [concept.derived] template concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v; -// [concept.convertible] -template -concept convertible_to = - is_convertible_v<_From, _To> && - requires(add_rvalue_reference_t<_From> (&__f)()) { - static_cast<_To>(__f()); - }; - -// [concept.commonref] -template -concept common_reference_with = - same_as, common_reference_t<_Up, _Tp>> && - convertible_to<_Tp, common_reference_t<_Tp, _Up>> && - convertible_to<_Up, common_reference_t<_Tp, _Up>>; - // [concept.common] template concept common_with = @@ -332,66 +314,6 @@ ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); }; -// [concept.booleantestable] -template -concept __boolean_testable_impl = convertible_to<_Tp, bool>; - -template -concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { - { !std::forward<_Tp>(__t) } -> __boolean_testable_impl; -}; - -// [concept.equalitycomparable] -template -concept __weakly_equality_comparable_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t == __u } -> __boolean_testable; - { __t != __u } -> __boolean_testable; - { __u == __t } -> __boolean_testable; - { __u != __t } -> __boolean_testable; - }; - -template -concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; - -template -concept equality_comparable_with = - equality_comparable<_Tp> && equality_comparable<_Up> && - common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && - equality_comparable< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __weakly_equality_comparable_with<_Tp, _Up>; - -// [concept.totallyordered] - -template -concept __partially_ordered_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t < __u } -> __boolean_testable; - { __t > __u } -> __boolean_testable; - { __t <= __u } -> __boolean_testable; - { __t >= __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - { __u > __t } -> __boolean_testable; - { __u <= __t } -> __boolean_testable; - { __u >= __t } -> __boolean_testable; - }; - -template -concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; - -template -concept totally_ordered_with = - totally_ordered<_Tp> && totally_ordered<_Up> && - equality_comparable_with<_Tp, _Up> && - totally_ordered< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __partially_ordered_with<_Tp, _Up>; - // [concepts.object] template concept movable = diff --git a/libcxx/include/functional b/libcxx/include/functional --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -135,6 +135,9 @@ bool operator()(const T& x, const T& y) const; }; +// [comparisons.three.way], class compare_three_way +struct compare_three_way; + template // in C++14 struct logical_and { bool operator()(const T& x, const T& y) const; @@ -488,6 +491,7 @@ */ #include <__algorithm/search.h> +#include <__compare/compare_three_way.h> #include <__config> #include <__debug> #include <__functional/binary_function.h> // TODO: deprecate diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -360,8 +360,12 @@ export * module __compare { + module cmp_alg { private header "__compare/cmp_alg.h" } module common_comparison_category { private header "__compare/common_comparison_category.h" } + module compare_three_way { private header "__compare/compare_three_way.h" } + module compare_three_way_result { private header "__compare/compare_three_way_result.h" } module ordering { private header "__compare/ordering.h" } + module three_way_comparable { private header "__compare/three_way_comparable.h" } } } module complex { @@ -371,6 +375,15 @@ module concepts { header "concepts" export * + + module __concepts { + module __boolean_testable { private header "__concepts/__boolean_testable.h" } + module convertible_to { private header "__concepts/convertible_to.h" } + module common_reference_with { private header "__concepts/common_reference_with.h" } + module equality_comparable { private header "__concepts/equality_comparable.h" } + module same_as { private header "__concepts/same_as.h" } + module totally_ordered { private header "__concepts/totally_ordered.h" } + } } module condition_variable { header "condition_variable" diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/compare/cmp_alg.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/compare/cmp_alg.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/compare/cmp_alg.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__compare/cmp_alg.h'}} +#include <__compare/cmp_alg.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/compare/compare_three_way.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/compare/compare_three_way.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/compare/compare_three_way.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__compare/compare_three_way.h'}} +#include <__compare/compare_three_way.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/compare/compare_three_way_result.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/compare/compare_three_way_result.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/compare/compare_three_way_result.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__compare/compare_three_way_result.h'}} +#include <__compare/compare_three_way_result.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/compare/three_way_comparable.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/compare/three_way_comparable.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/compare/three_way_comparable.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__compare/three_way_comparable.h'}} +#include <__compare/three_way_comparable.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/concepts/__boolean_testable.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/__boolean_testable.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/__boolean_testable.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__concepts/__boolean_testable.h'}} +#include <__concepts/__boolean_testable.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/concepts/common_reference_with.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/common_reference_with.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/common_reference_with.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__concepts/common_reference_with.h'}} +#include <__concepts/common_reference_with.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/concepts/convertible_to.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/convertible_to.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/convertible_to.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__concepts/convertible_to.h'}} +#include <__concepts/convertible_to.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/concepts/equality_comparable.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/equality_comparable.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/equality_comparable.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__concepts/equality_comparable.h'}} +#include <__concepts/equality_comparable.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/concepts/same_as.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/same_as.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/same_as.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__concepts/same_as.h'}} +#include <__concepts/same_as.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/concepts/totally_ordered.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/totally_ordered.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/concepts/totally_ordered.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__concepts/totally_ordered.h'}} +#include <__concepts/totally_ordered.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/__priority_tag.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/__priority_tag.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/__priority_tag.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/__priority_tag.h'}} +#include <__utility/__priority_tag.h> diff --git a/libcxx/test/std/library/description/conventions/type.descriptions/customization.point.object/cpo.pass.cpp b/libcxx/test/std/library/description/conventions/type.descriptions/customization.point.object/cpo.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/library/description/conventions/type.descriptions/customization.point.object/cpo.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// [customization.point.object] +// [range.adaptor.object] "A range adaptor object is a customization point object..." + +#include +#include +#include +#include +#include + +template +constexpr bool test(CPO& o, Args&&...) +{ + auto p = o; + using T = decltype(p); + + // The type of a customization point object, ignoring cv-qualifiers, shall model semiregular. + static_assert(std::semiregular); + + // All instances of a specific customization point object type shall be equal. + // (However, they need not support operator==, so there's nothing to test here.) + + // The type T of a customization point object, ignoring cv-qualifiers, shall model... + static_assert(std::invocable); + static_assert(std::invocable); + static_assert(std::invocable); + static_assert(std::invocable); + + return true; +} + +int main(int, char**) +{ + int a[10]; + int arrays[10][10]; + std::pair pairs[10]; + std::istringstream iss; + + // [iterator.cust] + static_assert(test(std::ranges::iter_move, a+0)); + static_assert(test(std::ranges::iter_swap, a+0, a+1)); + + // [cmp.alg] + static_assert(test(std::strong_order, 1, 2)); + static_assert(test(std::weak_order, 1, 2)); + static_assert(test(std::partial_order, 1, 2)); +// static_assert(test(std::compare_strong_order_fallback, 1, 2)); +// static_assert(test(std::compare_weak_order_fallback, 1, 2)); +// static_assert(test(std::compare_partial_order_fallback, 1, 2)); + + // [range.access] + static_assert(test(std::ranges::begin, a)); + static_assert(test(std::ranges::end, a)); + static_assert(test(std::ranges::cbegin, a)); + static_assert(test(std::ranges::cend, a)); +// static_assert(test(std::ranges::rbegin, a)); +// static_assert(test(std::ranges::rend, a)); +// static_assert(test(std::ranges::crbegin, a)); +// static_assert(test(std::ranges::crend, a)); + static_assert(test(std::ranges::size, a)); + static_assert(test(std::ranges::ssize, a)); + static_assert(test(std::ranges::empty, a)); + static_assert(test(std::ranges::data, a)); +// static_assert(test(std::ranges::cdata, a)); + + // [range.factories] + // views::empty is not a CPO +// static_assert(test(std::views::empty)); // technically not documented as a CPO yet +// static_assert(test(std::views::single, 4)); +// static_assert(test(std::views::iota, 1)); +// static_assert(test(std::views::iota, 1, 10)); +// static_assert(test(std::views::istream_view, iss)); // technically not documented as a CPO yet + + // [range.adaptors] + static_assert(test(std::views::all, a)); +// static_assert(test(std::views::filter, a, [](int x){ return x < 10; })); +// static_assert(test(std::views::transform, a, [](int x){ return x + 1; })); + static_assert(test(std::views::take, a, 10)); + static_assert(test(std::views::take_while, a, [](int x){ return x < 10; })); +// static_assert(test(std::views::drop, a, 10)); +// static_assert(test(std::views::drop_while, a, [](int x){ return x < 10; })); + static_assert(test(std::views::join, arrays)); + static_assert(test(std::views::lazy_split, a, 4)); + static_assert(test(std::views::split, a, 4)); + static_assert(test(std::views::counted, a, 10)); + static_assert(test(std::views::common, a)); + static_assert(test(std::views::reverse, a)); + static_assert(test(std::views::elements<0>, pairs)); + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/comparisons/compare_three_way.pass.cpp b/libcxx/test/std/utilities/function.objects/comparisons/compare_three_way.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/comparisons/compare_three_way.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// + +// compare_three_way + +#include +#include +#include + +#include "pointer_comparison_test_helper.h" + +template +constexpr auto test_sfinae(T t, U u) + -> decltype(std::compare_three_way()(t, u), std::true_type{}) + { return std::true_type{}; } + +constexpr auto test_sfinae(...) + { return std::false_type{}; } + +int main(int, char**) +{ + static_assert(std::compare_three_way()(1, 1) == (1 <=> 1)); + static_assert(std::compare_three_way()(1, 2) == (1 <=> 2)); + static_assert(std::compare_three_way()(2, 1) == (2 <=> 1)); + + do_pointer_comparison_test(std::compare_three_way()); + + static_assert(test_sfinae(1, 2)); + static_assert(!test_sfinae(1, nullptr)); + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/comparisons/transparent.pass.cpp b/libcxx/test/std/utilities/function.objects/comparisons/transparent.pass.cpp --- a/libcxx/test/std/utilities/function.objects/comparisons/transparent.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/comparisons/transparent.pass.cpp @@ -56,5 +56,9 @@ static_assert ( is_transparent>::value, "" ); static_assert ( is_transparent>::value, "" ); +#if TEST_STD_VER > 17 + static_assert(is_transparent); +#endif + return 0; }