diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp @@ -25,6 +25,7 @@ #include #include "almost_satisfies_types.h" +#include "boolean_testable.h" #include "test_iterators.h" struct NotEqualityComparable {}; @@ -247,6 +248,20 @@ } } + { + // check that the implicit conversion to bool works + { + StrictComparable a[] = {1, 2, 3, 4}; + auto ret = std::ranges::find(a, a + 4, StrictComparable{2}); + assert(ret == a + 1); + } + { + StrictComparable a[] = {1, 2, 3, 4}; + auto ret = std::ranges::find(a, StrictComparable{2}); + assert(ret == a + 1); + } + } + return true; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if.pass.cpp @@ -25,6 +25,7 @@ #include #include "almost_satisfies_types.h" +#include "boolean_testable.h" #include "test_iterators.h" struct Predicate { @@ -224,6 +225,20 @@ } } + { + // check that the implicit conversion to bool works + { + int a[] = {1, 2, 3, 4}; + auto ret = std::ranges::find_if(a, a + 4, [](const int& i) { return BooleanTestable{i == 3}; }); + assert(ret == a + 2); + } + { + int a[] = {1, 2, 3, 4}; + auto ret = std::ranges::find_if(a, [](const int& b) { return BooleanTestable{b == 3}; }); + assert(ret == a + 2); + } + } + return true; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if_not.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if_not.pass.cpp --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if_not.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find_if_not.pass.cpp @@ -25,6 +25,7 @@ #include #include "almost_satisfies_types.h" +#include "boolean_testable.h" #include "test_iterators.h" struct Predicate { @@ -218,6 +219,20 @@ } } + { + // check that the implicit conversion to bool works + { + int a[] = {1, 2, 3, 4}; + auto ret = std::ranges::find_if_not(a, a + 4, [](const int& i) { return BooleanTestable{i != 3}; }); + assert(ret == a + 2); + } + { + int a[] = {1, 2, 3, 4}; + auto ret = std::ranges::find_if_not(a, [](const int& b) { return BooleanTestable{b != 3}; }); + assert(ret == a + 2); + } + } + return true; } diff --git a/libcxx/test/support/boolean_testable.h b/libcxx/test/support/boolean_testable.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/boolean_testable.h @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#if TEST_STD_VER > 17 + +class BooleanTestable { +public: + 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 == rhs); + } + + constexpr BooleanTestable operator!() { + return BooleanTestable{!value_}; + } + + // 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_; +}; + +template +class StrictComparable { +public: + // this shouldn't be explicit to make it easier to initlaize inside arrays (which it almost always is) + constexpr StrictComparable(T value) : value_{value} {} + + friend constexpr BooleanTestable operator==(const StrictComparable& lhs, const StrictComparable& rhs) { + return (lhs.value_ == rhs.value_); + } + + friend constexpr BooleanTestable operator!=(const StrictComparable& lhs, const StrictComparable& rhs) { + return !(lhs == rhs); + } + +private: + T value_; +}; + +#endif // TEST_STD_VER > 17 + +#endif // LIBCXX_TEST_SUPPORT_BOOLEAN_TESTABLE_H