165 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H10#define LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H11 12#include "test_macros.h"13 14#include <iterator>15#include <utility>16 17#if TEST_STD_VER > 1718 19struct 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 explicit36 constexpr BooleanTestable(bool value) : value_{value} {}37 constexpr BooleanTestable(const BooleanTestable&) = delete;38 constexpr BooleanTestable(BooleanTestable&&) = delete;39 40private:41 bool value_;42};43 44static constexpr BooleanTestable yes(true);45static constexpr BooleanTestable no(false);46 47template <class T>48struct StrictComparable {49 StrictComparable() = default;50 51 // this shouldn't be explicit to make it easier to initialize inside arrays (which it almost always is)52 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 78auto StrictUnaryPredicate = []<class T>(StrictComparable<T> const& x) -> BooleanTestable const& {79 return x.value_ < 0 ? yes : no;80};81 82auto StrictBinaryPredicate =83 []<class T>(StrictComparable<T> const& x, StrictComparable<T> const& y) -> BooleanTestable const& {84 return x.value_ < y.value_ ? yes : no;85};86 87template <class It>88struct 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;93 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 156private:157 It iter_;158};159static_assert(std::forward_iterator<StrictBooleanIterator<int*>>);160static_assert(std::sentinel_for<StrictBooleanIterator<int*>, StrictBooleanIterator<int*>>);161 162#endif // TEST_STD_VER > 17163 164#endif // LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H165