MongoDB C++ Driver mongocxx-3.11.0
Loading...
Searching...
No Matches
operators.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
17#include <cstddef>
18#include <functional>
19#include <type_traits>
20
22
24
25namespace bsoncxx {
26namespace detail {
27
28template <typename L, typename R>
29auto is_equality_comparable_f(...) -> std::false_type;
30
31BSONCXX_PUSH_WARNINGS();
32BSONCXX_DISABLE_WARNING(GNU("-Wfloat-equal"));
33template <typename L, typename R>
34auto is_equality_comparable_f(int, bool b = false)
35 -> true_t<decltype((std::declval<const L&>() == std::declval<const R&>()) ? 0 : 0, //
36 (std::declval<const R&>() == std::declval<const L&>()) ? 0 : 0,
37 (std::declval<const L&>() != std::declval<const R&>()) ? 0 : 0,
38 (std::declval<const R&>() != std::declval<const L&>()) ? 0 : 0)>;
39BSONCXX_POP_WARNINGS();
40
41// Detect whether two types are equality-comparable.
42//
43// Requires L == R, L != R, R == L, and R != L.
44template <typename L, typename R = L>
45struct is_equality_comparable : decltype(is_equality_comparable_f<L, R>(0)) {};
46
47// Callable object and tag type for equality comparison.
48struct equal_to {
49 template <typename L, typename R>
50 constexpr requires_t<bool, is_equality_comparable<L, R>> //
51 operator()(L&& l, R&& r) const noexcept(noexcept(l == r)) {
52 return l == r;
53 }
54};
55
56// Derive from this class to define ADL-only operator== and operator!= on the basis of
57// an ADL-only tag_invoke(equal_to, l, r).
58class equality_operators {
59 template <typename L, typename R>
60 constexpr static auto impl(rank<1>, L& l, R& r) BSONCXX_RETURNS(tag_invoke(equal_to{}, l, r));
61
62 template <typename L, typename R>
63 constexpr static auto impl(rank<0>, L& l, R& r) BSONCXX_RETURNS(tag_invoke(equal_to{}, r, l));
64
65 // @cond DOXYGEN_DISABLE "Found ';' while parsing initializer list!"
66 template <typename Left, typename Other>
67 constexpr friend auto operator==(const Left& self, const Other& other)
68 BSONCXX_RETURNS(equality_operators::impl(rank<1>{}, self, other));
69 // @endcond
70
71 // @cond DOXYGEN_DISABLE "Found ';' while parsing initializer list!"
72 template <typename Left, typename Other>
73 constexpr friend auto operator!=(const Left& self, const Other& other)
74 BSONCXX_RETURNS(!equality_operators::impl(rank<1>{}, self, other));
75 // @endcond
76};
77
78// Very basic impl of C++20 std::strong_ordering.
79//
80// We don't need other weaker orderings yet, so this is all that we have.
81class strong_ordering {
82 signed char _c;
83 struct _construct {};
84
85 constexpr strong_ordering(_construct, signed char c) noexcept : _c(c) {}
86
87 public:
88 static const strong_ordering less;
89 static const strong_ordering greater;
90 static const strong_ordering equivalent;
91 static const strong_ordering equal;
92
93 constexpr strong_ordering(std::nullptr_t) noexcept : strong_ordering(_construct{}, 0) {}
94
95 constexpr bool operator==(strong_ordering o) const noexcept {
96 return _c == o._c;
97 }
98 constexpr bool operator!=(strong_ordering o) const noexcept {
99 return !(*this == o);
100 }
101#pragma push_macro("DEFOP")
102#undef DEFOP
103#define DEFOP(Op) \
104 constexpr bool operator Op(std::nullptr_t) const noexcept { \
105 return _c Op 0; \
106 } \
107 static_assert(true, "")
108 DEFOP(<);
109 DEFOP(>);
110 DEFOP(<=);
111 DEFOP(>=);
112#pragma pop_macro("DEFOP")
113
114 // nonstd: Swap greater/less values
115 constexpr strong_ordering inverted() const noexcept {
116 return *this < nullptr ? greater : *this > nullptr ? less : *this;
117 }
118};
119
120#pragma push_macro("INLINE_VAR")
121#undef INLINE_VAR
122#define INLINE_VAR BSONCXX_IF_GNU_LIKE([[gnu::weak]]) BSONCXX_IF_MSVC(__declspec(selectany))
123
124INLINE_VAR const strong_ordering strong_ordering::less =
125 strong_ordering(strong_ordering::_construct{}, -1);
126INLINE_VAR const strong_ordering strong_ordering::greater =
127 strong_ordering(strong_ordering::_construct{}, 1);
128INLINE_VAR const strong_ordering strong_ordering::equivalent =
129 strong_ordering(strong_ordering::_construct{}, 0);
130INLINE_VAR const strong_ordering strong_ordering::equal =
131 strong_ordering(strong_ordering::_construct{}, 0);
132
133#pragma pop_macro("INLINE_VAR")
134
135// Implements a three-way comparison between two objects. That is, in
136// a single operation, determine whether the left operand is less-than, greater-than,
137// or equal-to the right-hand operand.
138struct compare_three_way {
139 BSONCXX_PUSH_WARNINGS();
140 BSONCXX_DISABLE_WARNING(GNU("-Wfloat-equal"));
141 template <typename L,
142 typename R,
143 typename = decltype(std::declval<L>() < std::declval<R>()),
144 typename = decltype(std::declval<L>() == std::declval<R>())>
145 constexpr static strong_ordering impl(L const& l, R const& r, rank<1>) {
146 return (l < r) ? strong_ordering::less
147 : (l == r ? strong_ordering::equal //
148 : strong_ordering::greater);
149 }
150 BSONCXX_POP_WARNINGS();
151
152 template <typename L,
153 typename R,
154 typename = decltype(tag_invoke(
155 std::declval<compare_three_way>(), std::declval<L>(), std::declval<R>()))>
156 constexpr static strong_ordering impl(L const& l, R const& r, rank<2>) {
157 return tag_invoke(compare_three_way{}, l, r);
158 }
159
160 template <typename L, typename R>
161 constexpr auto operator()(L const& l, R const& r) const
162 BSONCXX_RETURNS((impl)(l, r, rank<2>{}));
163};
164
165// Inherit to define ADL-visible ordering operators based on an ADL-visible
166// implementation of tag_invoke(compare_three_way, l, r).
167struct ordering_operators {
168 template <typename L, typename R>
169 constexpr static auto impl(const L& l, const R& r, rank<1>)
170 BSONCXX_RETURNS(tag_invoke(compare_three_way{}, l, r));
171
172 template <typename L, typename R>
173 constexpr static auto impl(const L& l, const R& r, rank<0>)
174 BSONCXX_RETURNS(tag_invoke(compare_three_way{}, r, l).inverted());
175
176#pragma push_macro("DEFOP")
177#undef DEFOP
178#define DEFOP(Oper) \
179 template <typename L, typename R> \
180 constexpr friend auto operator Oper(const L& l, const R& r) \
181 BSONCXX_RETURNS(ordering_operators::impl(l, r, rank<1>{}) Oper nullptr)
182 DEFOP(<);
183 DEFOP(>);
184 DEFOP(<=);
185 DEFOP(>=);
186#pragma pop_macro("DEFOP")
187};
188
189template <typename L, typename R>
190std::false_type is_partially_ordered_with_f(rank<0>);
191
192template <typename L, typename R>
193auto is_partially_ordered_with_f(rank<1>)
194 -> true_t<decltype(std::declval<const L&>() > std::declval<const R&>()),
195 decltype(std::declval<const L&>() < std::declval<const R&>()),
196 decltype(std::declval<const L&>() >= std::declval<const R&>()),
197 decltype(std::declval<const L&>() <= std::declval<const R&>()),
198 decltype(std::declval<const R&>() < std::declval<const L&>()),
199 decltype(std::declval<const R&>() > std::declval<const L&>()),
200 decltype(std::declval<const R&>() <= std::declval<const L&>()),
201 decltype(std::declval<const R&>() >= std::declval<const L&>())>;
202
203template <typename T, typename U>
204struct is_partially_ordered_with : decltype(is_partially_ordered_with_f<T, U>(rank<1>{})) {};
205
206template <typename T>
207struct is_totally_ordered
208 : conjunction<is_equality_comparable<T>, is_partially_ordered_with<T, T>> {};
209
210template <typename T, typename U>
211struct is_totally_ordered_with : conjunction<is_totally_ordered<T>,
212 is_totally_ordered<U>,
213 is_equality_comparable<T, U>,
214 is_partially_ordered_with<T, U>> {};
215
216} // namespace detail
217} // namespace bsoncxx
218
220
The bsoncxx macro guard postlude header.
The bsoncxx macro guard prelude header.
bool operator==(const element &elem, const types::bson_value::view &v)
Convenience methods to compare for equality against a bson_value.
bool operator!=(const element &elem, const types::bson_value::view &v)
Convenience methods to compare for equality against a bson_value.
The top-level namespace within which all bsoncxx library entities are declared.
bool operator==(const v_noabi::view_or_value< View, Value > &lhs, const v_noabi::view_or_value< View, Value > &rhs)
bsoncxx::v_noabi::operator==(const v_noabi::view_or_value<View, Value>& lhs, const v_noabi::view_or_v...
bool operator!=(const v_noabi::view_or_value< View, Value > &lhs, const v_noabi::view_or_value< View, Value > &rhs)
bsoncxx::v_noabi::operator!=(const v_noabi::view_or_value<View, Value>& lhs, const v_noabi::view_or_v...
The top-level namespace reserved for the C++ standard library.
Provides <type_traits>-related polyfills for internal use.