File: compare.hh

package info (click to toggle)
dune-common 2.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,048 kB
  • sloc: cpp: 54,403; python: 4,136; sh: 1,657; makefile: 17
file content (129 lines) | stat: -rw-r--r-- 4,354 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_COMMON_STD_COMPARE_HH
#define DUNE_COMMON_STD_COMPARE_HH

#include <compare>
#include <concepts>
#include <type_traits>
#include <utility>

/**
 * \file
 * \brief This file provides some concepts introduced in the C++20 standard library
 * \c \<compare\> and \c \<concepts\> not yet available in all library implementation.
 *
 * The code is partially extracted from https://en.cppreference.com/w/cpp/utility/compare.
 */

namespace Dune::Std {
namespace Impl {

template <class T, class Cat>
concept comparesAs =
  std::same_as<std::common_comparison_category_t<T, Cat>, Cat>;

template <class T, class U>
concept weaklyEqualityComparableWith =
  requires(const std::remove_reference_t<T>& t,
           const std::remove_reference_t<U>& u)
  {
    { t == u } -> std::convertible_to<bool>;
    { t != u } -> std::convertible_to<bool>;
    { u == t } -> std::convertible_to<bool>;
    { u != t } -> std::convertible_to<bool>;
  };

template <class T, class U>
concept partiallyOrderedWith =
  requires(const std::remove_reference_t<T>& t,
           const std::remove_reference_t<U>& u)
  {
    { t <  u } -> std::convertible_to<bool>;
    { t >  u } -> std::convertible_to<bool>;
    { t <= u } -> std::convertible_to<bool>;
    { t >= u } -> std::convertible_to<bool>;
    { u <  t } -> std::convertible_to<bool>;
    { u >  t } -> std::convertible_to<bool>;
    { u <= t } -> std::convertible_to<bool>;
    { u >= t } -> std::convertible_to<bool>;
  };

template <class T, class U, class C = std::common_reference_t<const T&, const U&>>
concept comparisonCommonTypeWithImpl =
  std::same_as<std::common_reference_t<const T&, const U&>,
               std::common_reference_t<const U&, const T&>> &&
  requires
  {
    requires std::convertible_to<const T&, const C&> ||
      std::convertible_to<T, const C&>;
    requires std::convertible_to<const U&, const C&> ||
      std::convertible_to<U, const C&>;
  };

template <class T, class U>
concept comparisonCommonTypeWith =
  comparisonCommonTypeWithImpl<std::remove_cvref_t<T>, std::remove_cvref_t<U>>;

} // end namespace Impl

/**
 * \brief The concept `std::three_way_comparable` specifies that the three way
 * comparison `operator <=>` on `T` yield results consistent with the comparison
 * category implied by `Cat`.
 *
 * The standard implementation is available in libstdc++ >= 10 and libc++ >= 14.
 */
template <class T, class Cat = std::partial_ordering>
concept three_way_comparable =
  Impl::weaklyEqualityComparableWith<T, T> &&
  Impl::partiallyOrderedWith<T, T> &&
  requires(const std::remove_reference_t<T>& a,
           const std::remove_reference_t<T>& b)
  {
    { a <=> b } -> Impl::comparesAs<Cat>;
  };


/**
 * \brief The concept `std::three_way_comparable_with` specifies that the three
 * way comparison `operator <=>` on (possibly mixed) `T` and `U` operands yield
 * results consistent with the comparison category implied by `Cat`. Comparing
 * mixed operands yields results equivalent to comparing the operands converted
 * to their common type.
 *
 * The standard implementation is available in libstdc++ >= 10 and libc++ >= 14.
 */
template <class T, class U, class Cat = std::partial_ordering>
concept three_way_comparable_with =
  Std::three_way_comparable<T, Cat> &&
  Std::three_way_comparable<U, Cat> &&
  Impl::comparisonCommonTypeWith<T, U> &&
  Std::three_way_comparable<
    std::common_reference_t<
      const std::remove_reference_t<T>&,
      const std::remove_reference_t<U>&>, Cat> &&
  Impl::weaklyEqualityComparableWith<T, U> &&
  Impl::partiallyOrderedWith<T, U> &&
  requires(const std::remove_reference_t<T>& t,
           const std::remove_reference_t<U>& u)
  {
    { t <=> u } -> Impl::comparesAs<Cat>;
    { u <=> t } -> Impl::comparesAs<Cat>;
  };

//! A functor implementing the three-way comparison on the arguments
struct compare_three_way
{
  template <class T, class U>
  constexpr auto operator() (T&& t, U&& u) const
  {
    return std::forward<T>(t) <=> std::forward<U>(u);
  }
};

} // end namespace Dune::Std

#endif // DUNE_COMMON_STD_COMPARE_HH