Commit 8ce2675b authored by Ruslan Arutyunyan's avatar Ruslan Arutyunyan Committed by Kent Ross
Browse files

[libc++][compare] Implement three_way_comparable[_with] concepts

Implementation of `three_way_comparable` and `three_way_comparable_with` concepts from <compare> header.

Please note that I have temporarily removed `<compare>` header from `<utility>` due to cyclic dependency that prevents using `<concepts>` header in `<compare>` one.

I tried to quickly resolve those issues including applying suggestions from @cjdb and dive deeper by myself but the problem seems more complicated that we thought initially.

I am in progress to prepare the patch with resolving this cyclic dependency between headers but for now I decided to put all that I have to the review to unblock people that depend on that functionality. At first glance the patch with resolving cyclic dependency is not so small (unless I find the way to make it smaller and cleaner) so I don't want to mix everything to one review.

Reviewed By: ldionne, cjdb, #libc, Quuxplusone

Differential Revision: https://reviews.llvm.org/D103478
parent 1a88bd68
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ set(files
  __compare/common_comparison_category.h
  __compare/compare_three_way_result.h
  __compare/ordering.h
  __compare/three_way_comparable.h
  __concepts/arithmetic.h
  __concepts/assignable.h
  __concepts/boolean_testable.h
+58 −0
Original line number Diff line number Diff line
//===----------------------------------------------------------------------===//
//
// 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 <__compare/ordering.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 <type_traits>

#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)

template<class _Tp, class _Cat>
concept __compares_as =
  same_as<common_comparison_category_t<_Tp, _Cat>, _Cat>;

template<class _Tp, class _Cat = partial_ordering>
concept three_way_comparable =
  __weakly_equality_comparable_with<_Tp, _Tp> &&
  __partially_ordered_with<_Tp, _Tp> &&
  requires(__make_const_lvalue_ref<_Tp> __a, __make_const_lvalue_ref<_Tp> __b) {
    { __a <=> __b } -> __compares_as<_Cat>;
  };

template<class _Tp, class _Up, class _Cat = partial_ordering>
concept three_way_comparable_with =
  three_way_comparable<_Tp, _Cat> &&
  three_way_comparable<_Up, _Cat> &&
  common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
  three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> &&
  __weakly_equality_comparable_with<_Tp, _Up> &&
  __partially_ordered_with<_Tp, _Up> &&
  requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
    { __t <=> __u } -> __compares_as<_Cat>;
    { __u <=> __t } -> __compares_as<_Cat>;
  };

#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) && !defined(_LIBCPP_HAS_NO_CONCEPTS)

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H
+7 −0
Original line number Diff line number Diff line
@@ -35,6 +35,12 @@ namespace std {
  template<class... Ts>
    using common_comparison_category_t = typename common_comparison_category<Ts...>::type;

  // [cmp.concept], concept three_way_comparable
  template<class T, class Cat = partial_ordering>
    concept three_way_comparable = see below;
  template<class T, class U, class Cat = partial_ordering>
    concept three_way_comparable_with = see below;

  // [cmp.result], result of three-way comparison
  template<class T, class U = T> struct compare_three_way_result;

@@ -129,6 +135,7 @@ namespace std {
#include <__compare/common_comparison_category.h>
#include <__compare/compare_three_way_result.h>
#include <__compare/ordering.h>
#include <__compare/three_way_comparable.h>
#include <__config>

#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+1 −0
Original line number Diff line number Diff line
@@ -370,6 +370,7 @@ module std [system] {
      module common_comparison_category { private header "__compare/common_comparison_category.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 {
+16 −0
Original line number Diff line number Diff line
// -*- 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>
Loading