[libc++] [P1614] Implement std::compare_three_way.

Differential Revision: https://reviews.llvm.org/D110735
This commit is contained in:
Arthur O'Dwyer
2021-07-28 23:40:29 -04:00
parent f341161689
commit 3df094d31e
10 changed files with 196 additions and 1 deletions

View File

@@ -4,7 +4,7 @@ Section,Description,Dependencies,Assignee,Complete
| `[cmp.result] <https://wg21.link/cmp.result>`_,| `compare_three_way_result <https://reviews.llvm.org/D103581>`_,None,Arthur O'Dwyer,|Complete|
| `[expos.only.func] <https://wg21.link/expos.only.func>`_,"| `synth-three-way <https://reviews.llvm.org/D107721>`_
| `synth-three-way-result <https://reviews.llvm.org/D107721>`_",[cmp.concept],Kent Ross,|Complete|
| `[comparisons.three.way] <https://wg21.link/comparisons.three.way>`_,| `compare_three_way <https://reviews.llvm.org/D80899>`_,[cmp.concept],Christopher Di Bella,|In Progress|
| `[comparisons.three.way] <https://wg21.link/comparisons.three.way>`_,| `compare_three_way <https://reviews.llvm.org/D80899>`_,[cmp.concept],Arthur O'Dwyer,|Complete|
| `[cmp.alg] <https://wg21.link/cmp.alg>`_,"| `strong_order <https://reviews.llvm.org/D107036>`_
| `weak_order <https://reviews.llvm.org/D107036>`_
| `partial_order <https://reviews.llvm.org/D107036>`_",None,Arthur O'Dwyer,|In Progress|
1 Section Description Dependencies Assignee Complete
4 | `[expos.only.func] <https://wg21.link/expos.only.func>`_ | `synth-three-way <https://reviews.llvm.org/D107721>`_ | `synth-three-way-result <https://reviews.llvm.org/D107721>`_ [cmp.concept] Kent Ross |Complete|
5 | `[comparisons.three.way] <https://wg21.link/comparisons.three.way>`_ | `compare_three_way <https://reviews.llvm.org/D80899>`_ [cmp.concept] Christopher Di Bella Arthur O'Dwyer |In Progress| |Complete|
6 | `[cmp.alg] <https://wg21.link/cmp.alg>`_ | `strong_order <https://reviews.llvm.org/D107036>`_ | `weak_order <https://reviews.llvm.org/D107036>`_ | `partial_order <https://reviews.llvm.org/D107036>`_ None Arthur O'Dwyer |In Progress|
7 | `[alg.three.way] <https://wg21.link/alg.three.way>`_ | `lexicographical_compare_three_way <https://reviews.llvm.org/D80902>`_ [comparisons.three.way] Christopher Di Bella |In Progress|
8 | `[coroutine.handle.compare] <https://wg21.link/coroutine.handle.compare>`_ | coroutine_handle [comparisons.three.way] Unassigned |Not Started|
9 | `[pairs.spec] <https://wg21.link/pairs.spec>`_ | `pair <https://reviews.llvm.org/D107721>`_ [expos.only.func] Kent Ross |Complete|
10 | `[syserr.errcat.nonvirtuals] <https://wg21.link/syserr.errcat.nonvirtuals>`_ | error_category [comparisons.three.way] Unassigned |Not Started|

View File

@@ -102,6 +102,7 @@ set(files
__charconv/from_chars_result.h
__charconv/to_chars_result.h
__compare/common_comparison_category.h
__compare/compare_three_way.h
__compare/compare_three_way_result.h
__compare/is_eq.h
__compare/ordering.h

View File

@@ -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) && !defined(_LIBCPP_HAS_NO_CONCEPTS)
struct _LIBCPP_TEMPLATE_VIS compare_three_way
{
template<class _T1, class _T2>
requires three_way_comparable_with<_T1, _T2>
constexpr _LIBCPP_HIDE_FROM_ABI
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) && !defined(_LIBCPP_HAS_NO_CONCEPTS)
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___COMPARE_COMPARE_THREE_WAY_H

View File

@@ -47,6 +47,9 @@ namespace std {
template<class T, class U = T>
using compare_three_way_result_t = typename compare_three_way_result<T, U>::type;
// [comparisons.three.way], class compare_three_way
struct compare_three_way; // C++20
// [cmp.alg], comparison algorithms
template<class T> constexpr strong_ordering strong_order(const T& a, const T& b);
template<class T> constexpr weak_ordering weak_order(const T& a, const T& b);
@@ -133,6 +136,7 @@ namespace std {
*/
#include <__compare/common_comparison_category.h>
#include <__compare/compare_three_way.h>
#include <__compare/compare_three_way_result.h>
#include <__compare/is_eq.h>
#include <__compare/ordering.h>

View File

@@ -135,6 +135,9 @@ struct less_equal {
bool operator()(const T& x, const T& y) const;
};
// [comparisons.three.way], class compare_three_way
struct compare_three_way;
template <class T> // <class T=void> in C++14
struct logical_and {
bool operator()(const T& x, const T& y) const;
@@ -488,6 +491,7 @@ POLICY: For non-variadic implementations, the number of arguments is limited
*/
#include <__algorithm/search.h>
#include <__compare/compare_three_way.h>
#include <__config>
#include <__debug>
#include <__functional/binary_function.h> // TODO: deprecate

View File

@@ -372,6 +372,7 @@ module std [system] {
module __compare {
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 is_eq { private header "__compare/is_eq.h" }
module ordering { private header "__compare/ordering.h" }

View File

@@ -0,0 +1,15 @@
//===----------------------------------------------------------------------===//
//
// 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>

View File

@@ -0,0 +1,83 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts
// <compare>
// <functional>
// compare_three_way
#include <compare>
#include <cassert>
#include <limits>
#include <type_traits>
#include "pointer_comparison_test_helper.h"
template<class T, class U>
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{}; }
struct NotThreeWayComparable {
std::strong_ordering operator<=>(const NotThreeWayComparable&) const;
};
ASSERT_SAME_TYPE(std::compare_three_way_result_t<NotThreeWayComparable>, std::strong_ordering);
static_assert(!std::three_way_comparable<NotThreeWayComparable>); // it lacks operator==
struct WeaklyOrdered {
int i;
friend constexpr std::weak_ordering operator<=>(const WeaklyOrdered&, const WeaklyOrdered&) = default;
};
constexpr bool test()
{
ASSERT_SAME_TYPE(decltype(std::compare_three_way()(1, 1)), std::strong_ordering);
assert(std::compare_three_way()(1, 2) == std::strong_ordering::less);
assert(std::compare_three_way()(1, 1) == std::strong_ordering::equal);
assert(std::compare_three_way()(2, 1) == std::strong_ordering::greater);
ASSERT_SAME_TYPE(decltype(std::compare_three_way()(WeaklyOrdered{1}, WeaklyOrdered{2})), std::weak_ordering);
assert(std::compare_three_way()(WeaklyOrdered{1}, WeaklyOrdered{2}) == std::weak_ordering::less);
assert(std::compare_three_way()(WeaklyOrdered{1}, WeaklyOrdered{1}) == std::weak_ordering::equivalent);
assert(std::compare_three_way()(WeaklyOrdered{2}, WeaklyOrdered{1}) == std::weak_ordering::greater);
ASSERT_SAME_TYPE(decltype(std::compare_three_way()(1.0, 1.0)), std::partial_ordering);
double nan = std::numeric_limits<double>::quiet_NaN();
assert(std::compare_three_way()(1.0, 2.0) == std::partial_ordering::less);
assert(std::compare_three_way()(1.0, 1.0) == std::partial_ordering::equivalent);
assert(std::compare_three_way()(2.0, 1.0) == std::partial_ordering::greater);
assert(std::compare_three_way()(nan, nan) == std::partial_ordering::unordered);
// Try heterogeneous comparison.
ASSERT_SAME_TYPE(decltype(std::compare_three_way()(42.0, 42)), std::partial_ordering);
assert(std::compare_three_way()(42.0, 42) == std::partial_ordering::equivalent);
ASSERT_SAME_TYPE(decltype(std::compare_three_way()(42, 42.0)), std::partial_ordering);
assert(std::compare_three_way()(42, 42.0) == std::partial_ordering::equivalent);
return true;
}
int main(int, char**)
{
test();
static_assert(test());
do_pointer_comparison_test(std::compare_three_way());
static_assert(test_sfinae(1, 2));
static_assert(!test_sfinae(1, nullptr));
static_assert(!test_sfinae(NotThreeWayComparable(), NotThreeWayComparable()));
return 0;
}

View File

@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts
// <functional>
// Test that std::compare_three_way is defined in <functional>,
// not only in <compare>.
#include <functional>
#include <cassert>
int main(int, char**)
{
assert(std::compare_three_way()(1, 2) < 0);
assert(std::compare_three_way()(1, 1) == 0);
assert(std::compare_three_way()(2, 1) > 0);
return 0;
}

View File

@@ -0,0 +1,19 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts
#include <functional>
template<class T>
concept Transparent = requires {
typename T::is_transparent;
};
static_assert(Transparent<std::compare_three_way>);