MongoDB C++ Driver 4.2.0
Loading...
Searching...
No Matches
compare.hpp
Go to the documentation of this file.
1// Copyright 2009-present MongoDB, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
18
21
22#include <cstddef>
23#include <utility>
24
25namespace bsoncxx {
26namespace detail {
27
28// Callable object and tag type for equality comparison.
29struct equal_to {
30 template <typename L, typename R>
31 constexpr requires_t<bool, is_equality_comparable<L, R>> operator()(L&& l, R&& r) const noexcept(noexcept(l == r)) {
32 return l == r;
33 }
34};
35
36// Derive from this class to define ADL-only operator== and operator!= on the basis of
37// an ADL-only tag_invoke(equal_to, l, r).
38class equality_operators {
39 template <typename L, typename R>
40 constexpr static auto impl(rank<1>, L& l, R& r) BSONCXX_PRIVATE_RETURNS(tag_invoke(equal_to{}, l, r));
41
42 template <typename L, typename R>
43 constexpr static auto impl(rank<0>, L& l, R& r) BSONCXX_PRIVATE_RETURNS(tag_invoke(equal_to{}, r, l));
44
45 // @cond DOXYGEN_DISABLE "Found ';' while parsing initializer list!"
46 template <typename Left, typename Other>
47 constexpr friend auto operator==(Left const& self, Other const& other)
48 BSONCXX_PRIVATE_RETURNS(equality_operators::impl(rank<1>{}, self, other));
49 // @endcond
50
51 // @cond DOXYGEN_DISABLE "Found ';' while parsing initializer list!"
52 template <typename Left, typename Other>
53 constexpr friend auto operator!=(Left const& self, Other const& other)
54 BSONCXX_PRIVATE_RETURNS(!equality_operators::impl(rank<1>{}, self, other));
55 // @endcond
56};
57
58// Very basic impl of C++20 std::strong_ordering.
59//
60// We don't need other weaker orderings yet, so this is all that we have.
61class strong_ordering {
62 signed char _c;
63 struct _construct {};
64
65 constexpr strong_ordering(_construct, signed char c) noexcept : _c(c) {}
66
67 public:
68 static strong_ordering const less;
69 static strong_ordering const greater;
70 static strong_ordering const equivalent;
71 static strong_ordering const equal;
72
73 constexpr strong_ordering(std::nullptr_t) noexcept : strong_ordering(_construct{}, 0) {}
74
75 constexpr bool operator==(strong_ordering o) const noexcept {
76 return _c == o._c;
77 }
78 constexpr bool operator!=(strong_ordering o) const noexcept {
79 return !(*this == o);
80 }
81#pragma push_macro("DEFOP")
82#undef DEFOP
83#define DEFOP(Op) \
84 constexpr bool operator Op(std::nullptr_t) const noexcept { \
85 return _c Op 0; \
86 } \
87 static_assert(true, "")
88 DEFOP(<);
89 DEFOP(>);
90 DEFOP(<=);
91 DEFOP(>=);
92#pragma pop_macro("DEFOP")
93
94 // nonstd: Swap greater/less values
95 constexpr strong_ordering inverted() const noexcept;
96};
97
98BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::less =
99 strong_ordering(strong_ordering::_construct{}, -1);
100BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::greater =
101 strong_ordering(strong_ordering::_construct{}, 1);
102BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::equivalent =
103 strong_ordering(strong_ordering::_construct{}, 0);
104BSONCXX_PRIVATE_INLINE_CXX17 strong_ordering const strong_ordering::equal =
105 strong_ordering(strong_ordering::_construct{}, 0);
106
107// Define out-of-line to avoid GCC error: ‘bsoncxx::detail::strong_ordering::*’ declared weak after being used
108inline constexpr strong_ordering strong_ordering::inverted() const noexcept {
109 return *this < nullptr ? greater : *this > nullptr ? less : *this;
110}
111
112// Implements a three-way comparison between two objects. That is, in
113// a single operation, determine whether the left operand is less-than, greater-than,
114// or equal-to the right-hand operand.
115struct compare_three_way {
116 BSONCXX_PRIVATE_WARNINGS_PUSH();
117 BSONCXX_PRIVATE_WARNINGS_DISABLE(GNU("-Wfloat-equal"));
118 template <
119 typename L,
120 typename R,
121 typename = decltype(std::declval<L>() < std::declval<R>()),
122 typename = decltype(std::declval<L>() == std::declval<R>())>
123 constexpr static strong_ordering impl(L const& l, R const& r, rank<1>) {
124 return (l < r) ? strong_ordering::less : (l == r ? strong_ordering::equal : strong_ordering::greater);
125 }
126 BSONCXX_PRIVATE_WARNINGS_POP();
127
128 template <
129 typename L,
130 typename R,
131 typename = decltype(tag_invoke(std::declval<compare_three_way>(), std::declval<L>(), std::declval<R>()))>
132 constexpr static strong_ordering impl(L const& l, R const& r, rank<2>) {
133 return tag_invoke(compare_three_way{}, l, r);
134 }
135
136 template <typename L, typename R>
137 constexpr auto operator()(L const& l, R const& r) const BSONCXX_PRIVATE_RETURNS((impl)(l, r, rank<2>{}));
138};
139
140// Inherit to define ADL-visible ordering operators based on an ADL-visible
141// implementation of tag_invoke(compare_three_way, l, r).
142struct ordering_operators {
143 template <typename L, typename R>
144 constexpr static auto impl(L const& l, R const& r, rank<1>)
145 BSONCXX_PRIVATE_RETURNS(tag_invoke(compare_three_way{}, l, r));
146
147 template <typename L, typename R>
148 constexpr static auto impl(L const& l, R const& r, rank<0>)
149 BSONCXX_PRIVATE_RETURNS(tag_invoke(compare_three_way{}, r, l).inverted());
150
151#pragma push_macro("DEFOP")
152#undef DEFOP
153#define DEFOP(Oper) \
154 template <typename L, typename R> \
155 constexpr friend auto operator Oper(L const& l, R const& r) \
156 BSONCXX_PRIVATE_RETURNS(ordering_operators::impl(l, r, rank<1>{}) Oper nullptr)
157 DEFOP(<);
158 DEFOP(>);
159 DEFOP(<=);
160 DEFOP(>=);
161#pragma pop_macro("DEFOP")
162};
163
164} // namespace detail
165} // namespace bsoncxx
166
168
For internal use only!
The bsoncxx v1 macro guard postlude header.
The bsoncxx v1 macro guard prelude header.
bool operator!=(element const &lhs, v_noabi::types::bson_value::view const &rhs)
Convenience methods to compare for equality against a bson_value.
Definition element.hpp:105
The top-level namespace within which all bsoncxx library entities are declared.
bool operator==(view_or_value< View, Value > const &lhs, view_or_value< View, Value > const &rhs)
Compare view_or_value objects for (in)equality.
Definition view_or_value.hpp:151
For internal use only!