From: Nikolas Klauser Date: Thu, 7 Apr 2022 10:01:49 +0000 (+0200) Subject: [libc++][ranges] Add implicit conversion to bool test for ranges::find{, if, if_not} X-Git-Tag: upstream/15.0.7~11180 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cd7b444078e6a93bbe3cf0122f9aef7213b418bb;p=platform%2Fupstream%2Fllvm.git [libc++][ranges] Add implicit conversion to bool test for ranges::find{, if, if_not} Reviewed By: ldionne, var-const, #libc Spies: libcxx-commits Differential Revision: https://reviews.llvm.org/D122011 --- 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 index d7c38bb..ad11098 100644 --- 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 @@ constexpr bool test() { } } + { + // 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 index d5b38b1..c714769 100644 --- 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 @@ constexpr bool test() { } } + { + // 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 index 30d14c0..f4814ee 100644 --- 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 @@ constexpr bool test() { } } + { + // 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 index 0000000..9d4f629 --- /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