//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H #define LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H #include "test_macros.h" #include #include #if TEST_STD_VER > 17 struct BooleanTestable { constexpr operator bool() const { return value_; } friend constexpr BooleanTestable operator==(const BooleanTestable& lhs, const BooleanTestable& rhs) { return lhs.value_ == rhs.value_; } friend constexpr BooleanTestable operator!=(const BooleanTestable& lhs, const BooleanTestable& rhs) { return lhs.value_ != rhs.value_; } constexpr BooleanTestable&& operator!() && { value_ = !value_; return std::move(*this); } // this class should behave like a bool, so the constructor shouldn't be explicit constexpr BooleanTestable(bool value) : value_{value} {} constexpr BooleanTestable(const BooleanTestable&) = delete; constexpr BooleanTestable(BooleanTestable&&) = delete; private: bool value_; }; static constexpr BooleanTestable yes(true); static constexpr BooleanTestable no(false); template struct StrictComparable { StrictComparable() = default; // this shouldn't be explicit to make it easier to initialize inside arrays (which it almost always is) constexpr StrictComparable(T value) : value_{value} {} friend constexpr BooleanTestable const& operator==(StrictComparable const& a, StrictComparable const& b) { return a.value_ == b.value_ ? yes : no; } friend constexpr BooleanTestable const& operator!=(StrictComparable const& a, StrictComparable const& b) { return a.value_ != b.value_ ? yes : no; } friend constexpr BooleanTestable const& operator<(StrictComparable const& a, StrictComparable const& b) { return a.value_ < b.value_ ? yes : no; } friend constexpr BooleanTestable const& operator<=(StrictComparable const& a, StrictComparable const& b) { return a.value_ <= b.value_ ? yes : no; } friend constexpr BooleanTestable const& operator>(StrictComparable const& a, StrictComparable const& b) { return a.value_ > b.value_ ? yes : no; } friend constexpr BooleanTestable const& operator>=(StrictComparable const& a, StrictComparable const& b) { return a.value_ >= b.value_ ? yes : no; } T value_; }; auto StrictUnaryPredicate = [](StrictComparable const& x) -> BooleanTestable const& { return x.value_ < 0 ? yes : no; }; auto StrictBinaryPredicate = [](StrictComparable const& x, StrictComparable const& y) -> BooleanTestable const& { return x.value_ < y.value_ ? yes : no; }; template struct StrictBooleanIterator { using value_type = typename std::iterator_traits::value_type; using reference = typename std::iterator_traits::reference; using difference_type = typename std::iterator_traits::difference_type; constexpr StrictBooleanIterator() = default; constexpr explicit StrictBooleanIterator(It it) : iter_(it) {} constexpr reference operator*() const { return *iter_; } constexpr reference operator[](difference_type n) const { return iter_[n]; } constexpr StrictBooleanIterator& operator++() { ++iter_; return *this; } constexpr StrictBooleanIterator operator++(int) { auto copy = *this; ++iter_; return copy; } constexpr StrictBooleanIterator& operator--() { --iter_; return *this; } constexpr StrictBooleanIterator operator--(int) { auto copy = *this; --iter_; return copy; } constexpr StrictBooleanIterator& operator+=(difference_type n) { iter_ += n; return *this; } constexpr StrictBooleanIterator& operator-=(difference_type n) { iter_ -= n; return *this; } friend constexpr StrictBooleanIterator operator+(StrictBooleanIterator x, difference_type n) { x += n; return x; } friend constexpr StrictBooleanIterator operator+(difference_type n, StrictBooleanIterator x) { x += n; return x; } friend constexpr StrictBooleanIterator operator-(StrictBooleanIterator x, difference_type n) { x -= n; return x; } friend constexpr difference_type operator-(StrictBooleanIterator x, StrictBooleanIterator y) { return x.iter_ - y.iter_; } constexpr BooleanTestable const& operator==(StrictBooleanIterator const& other) const { return iter_ == other.iter_ ? yes : no; } constexpr BooleanTestable const& operator!=(StrictBooleanIterator const& other) const { return iter_ != other.iter_ ? yes : no; } constexpr BooleanTestable const& operator<(StrictBooleanIterator const& other) const { return iter_ < other.iter_ ? yes : no; } constexpr BooleanTestable const& operator<=(StrictBooleanIterator const& other) const { return iter_ <= other.iter_ ? yes : no; } constexpr BooleanTestable const& operator>(StrictBooleanIterator const& other) const { return iter_ > other.iter_ ? yes : no; } constexpr BooleanTestable const& operator>=(StrictBooleanIterator const& other) const { return iter_ >= other.iter_ ? yes : no; } private: It iter_; }; static_assert(std::forward_iterator>); static_assert(std::sentinel_for, StrictBooleanIterator>); #endif // TEST_STD_VER > 17 #endif // LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H