xref: /llvm-project/libcxx/test/support/boolean_testable.h (revision f5832bab6f5024cabe32a9f668b7f44e6b7cfef5)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H
10 #define LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H
11 
12 #include "test_macros.h"
13 
14 #include <iterator>
15 #include <utility>
16 
17 #if TEST_STD_VER > 17
18 
19 struct BooleanTestable {
20   constexpr operator bool() const { return value_; }
21 
22   friend constexpr BooleanTestable operator==(const BooleanTestable& lhs, const BooleanTestable& rhs) {
23     return lhs.value_ == rhs.value_;
24   }
25 
26   friend constexpr BooleanTestable operator!=(const BooleanTestable& lhs, const BooleanTestable& rhs) {
27     return lhs.value_ != rhs.value_;
28   }
29 
30   constexpr BooleanTestable&& operator!() && {
31     value_ = !value_;
32     return std::move(*this);
33   }
34 
35   // this class should behave like a bool, so the constructor shouldn't be explicit
BooleanTestableBooleanTestable36   constexpr BooleanTestable(bool value) : value_{value} {}
37   constexpr BooleanTestable(const BooleanTestable&) = delete;
38   constexpr BooleanTestable(BooleanTestable&&)      = delete;
39 
40 private:
41   bool value_;
42 };
43 
44 static constexpr BooleanTestable yes(true);
45 static constexpr BooleanTestable no(false);
46 
47 template <class T>
48 struct StrictComparable {
49   StrictComparable() = default;
50 
51   // this shouldn't be explicit to make it easier to initialize inside arrays (which it almost always is)
StrictComparableStrictComparable52   constexpr StrictComparable(T value) : value_{value} {}
53 
54   friend constexpr BooleanTestable const& operator==(StrictComparable const& a, StrictComparable const& b) {
55     return a.value_ == b.value_ ? yes : no;
56   }
57 
58   friend constexpr BooleanTestable const& operator!=(StrictComparable const& a, StrictComparable const& b) {
59     return a.value_ != b.value_ ? yes : no;
60   }
61 
62   friend constexpr BooleanTestable const& operator<(StrictComparable const& a, StrictComparable const& b) {
63     return a.value_ < b.value_ ? yes : no;
64   }
65   friend constexpr BooleanTestable const& operator<=(StrictComparable const& a, StrictComparable const& b) {
66     return a.value_ <= b.value_ ? yes : no;
67   }
68   friend constexpr BooleanTestable const& operator>(StrictComparable const& a, StrictComparable const& b) {
69     return a.value_ > b.value_ ? yes : no;
70   }
71   friend constexpr BooleanTestable const& operator>=(StrictComparable const& a, StrictComparable const& b) {
72     return a.value_ >= b.value_ ? yes : no;
73   }
74 
75   T value_;
76 };
77 
78 auto StrictUnaryPredicate = []<class T>(StrictComparable<T> const& x) -> BooleanTestable const& {
79   return x.value_ < 0 ? yes : no;
80 };
81 
82 auto StrictBinaryPredicate =
83     []<class T>(StrictComparable<T> const& x, StrictComparable<T> const& y) -> BooleanTestable const& {
84   return x.value_ < y.value_ ? yes : no;
85 };
86 
87 template <class It>
88 struct StrictBooleanIterator {
89   using value_type                  = typename std::iterator_traits<It>::value_type;
90   using reference                   = typename std::iterator_traits<It>::reference;
91   using difference_type             = typename std::iterator_traits<It>::difference_type;
92   constexpr StrictBooleanIterator() = default;
StrictBooleanIteratorStrictBooleanIterator93   constexpr explicit StrictBooleanIterator(It it) : iter_(it) {}
94   constexpr reference operator*() const { return *iter_; }
95   constexpr reference operator[](difference_type n) const { return iter_[n]; }
96   constexpr StrictBooleanIterator& operator++() {
97     ++iter_;
98     return *this;
99   }
100   constexpr StrictBooleanIterator operator++(int) {
101     auto copy = *this;
102     ++iter_;
103     return copy;
104   }
105   constexpr StrictBooleanIterator& operator--() {
106     --iter_;
107     return *this;
108   }
109   constexpr StrictBooleanIterator operator--(int) {
110     auto copy = *this;
111     --iter_;
112     return copy;
113   }
114   constexpr StrictBooleanIterator& operator+=(difference_type n) {
115     iter_ += n;
116     return *this;
117   }
118   constexpr StrictBooleanIterator& operator-=(difference_type n) {
119     iter_ -= n;
120     return *this;
121   }
122   friend constexpr StrictBooleanIterator operator+(StrictBooleanIterator x, difference_type n) {
123     x += n;
124     return x;
125   }
126   friend constexpr StrictBooleanIterator operator+(difference_type n, StrictBooleanIterator x) {
127     x += n;
128     return x;
129   }
130   friend constexpr StrictBooleanIterator operator-(StrictBooleanIterator x, difference_type n) {
131     x -= n;
132     return x;
133   }
134   friend constexpr difference_type operator-(StrictBooleanIterator x, StrictBooleanIterator y) {
135     return x.iter_ - y.iter_;
136   }
137   constexpr BooleanTestable const& operator==(StrictBooleanIterator const& other) const {
138     return iter_ == other.iter_ ? yes : no;
139   }
140   constexpr BooleanTestable const& operator!=(StrictBooleanIterator const& other) const {
141     return iter_ != other.iter_ ? yes : no;
142   }
143   constexpr BooleanTestable const& operator<(StrictBooleanIterator const& other) const {
144     return iter_ < other.iter_ ? yes : no;
145   }
146   constexpr BooleanTestable const& operator<=(StrictBooleanIterator const& other) const {
147     return iter_ <= other.iter_ ? yes : no;
148   }
149   constexpr BooleanTestable const& operator>(StrictBooleanIterator const& other) const {
150     return iter_ > other.iter_ ? yes : no;
151   }
152   constexpr BooleanTestable const& operator>=(StrictBooleanIterator const& other) const {
153     return iter_ >= other.iter_ ? yes : no;
154   }
155 
156 private:
157   It iter_;
158 };
159 static_assert(std::forward_iterator<StrictBooleanIterator<int*>>);
160 static_assert(std::sentinel_for<StrictBooleanIterator<int*>, StrictBooleanIterator<int*>>);
161 
162 #endif // TEST_STD_VER > 17
163 
164 #endif // LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H
165