//===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // ADDITIONAL_COMPILE_FLAGS(gcc): -Wno-bool-compare // ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-sign-compare // MSVC warning C4245: conversion from 'int' to 'wchar_t', signed/unsigned mismatch // MSVC warning C4305: truncation from 'int' to 'bool' // MSVC warning C4310: cast truncates constant value // MSVC warning C4389: '==': signed/unsigned mismatch // MSVC warning C4805: '==': unsafe mix of type 'char' and type 'bool' in operation // ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4245 /wd4305 /wd4310 /wd4389 /wd4805 // // template // requires HasEqualTo // constexpr Iter // constexpr after C++17 // find(Iter first, Iter last, const T& value); #include #include #include #include #include #include "test_macros.h" #include "test_iterators.h" #include "type_algorithms.h" static std::vector comparable_data; template struct Test { template TEST_CONSTEXPR_CXX20 void operator()() { ArrayT arr[] = { ArrayT(1), ArrayT(2), ArrayT(3), ArrayT(4), ArrayT(5), ArrayT(6), ArrayT(7), ArrayT(8), ArrayT(9), ArrayT(10)}; static_assert(std::is_same::value, ""); { // first element matches Iter iter = std::find(Iter(arr), Iter(arr + 10), CompareT(1)); assert(*iter == ArrayT(1)); assert(base(iter) == arr); } { // range is empty; return last Iter iter = std::find(Iter(arr), Iter(arr), CompareT(1)); assert(base(iter) == arr); } { // if multiple elements match, return the first match ArrayT data[] = { ArrayT(1), ArrayT(2), ArrayT(3), ArrayT(4), ArrayT(5), ArrayT(6), ArrayT(7), ArrayT(5), ArrayT(4)}; Iter iter = std::find(Iter(std::begin(data)), Iter(std::end(data)), CompareT(5)); assert(*iter == ArrayT(5)); assert(base(iter) == data + 4); } { // some element matches Iter iter = std::find(Iter(arr), Iter(arr + 10), CompareT(6)); assert(*iter == ArrayT(6)); assert(base(iter) == arr + 5); } { // last element matches Iter iter = std::find(Iter(arr), Iter(arr + 10), CompareT(10)); assert(*iter == ArrayT(10)); assert(base(iter) == arr + 9); } { // if no element matches, last is returned Iter iter = std::find(Iter(arr), Iter(arr + 10), CompareT(20)); assert(base(iter) == arr + 10); } if (!TEST_IS_CONSTANT_EVALUATED) comparable_data.clear(); } }; template class Comparable { IndexT index_; static IndexT init_index(IndexT i) { IndexT size = static_cast(comparable_data.size()); comparable_data.push_back(i); return size; } public: Comparable(IndexT i) : index_(init_index(i)) {} friend bool operator==(const Comparable& lhs, const Comparable& rhs) { return comparable_data[lhs.index_] == comparable_data[rhs.index_]; } }; #if TEST_STD_VER >= 20 template class TriviallyComparable { ElementT el_; public: explicit constexpr TriviallyComparable(ElementT el) : el_(el) {} bool operator==(const TriviallyComparable&) const = default; }; #endif template struct TestTypes { template TEST_CONSTEXPR_CXX20 void operator()() { types::for_each(types::cpp17_input_iterator_list(), Test()); } }; void test_deque() { { // empty deque std::deque data; assert(std::find(data.begin(), data.end(), 4) == data.end()); } { // single element - match std::deque data; data.push_back(4); assert(std::find(data.begin(), data.end(), 4) == data.begin()); } { // single element - no match std::deque data; data.push_back(3); assert(std::find(data.begin(), data.end(), 4) == data.end()); } // many elements int sizes[] = {2, 3, 1023, 1024, 1025, 2047, 2048, 2049}; for (auto size : sizes) { { // last element match std::deque data; data.resize(size); std::fill(data.begin(), data.end(), 3); data[size - 1] = 4; assert(std::find(data.begin(), data.end(), 4) == data.end() - 1); } { // second-last element match std::deque data; data.resize(size); std::fill(data.begin(), data.end(), 3); data[size - 2] = 4; assert(std::find(data.begin(), data.end(), 4) == data.end() - 2); } { // no match std::deque data; data.resize(size); std::fill(data.begin(), data.end(), 3); assert(std::find(data.begin(), data.end(), 4) == data.end()); } } } template struct TestIntegerPromotions1 { template TEST_CONSTEXPR_CXX20 void test(T val, U to_find) { bool expect_match = val == to_find; assert(std::find(&val, &val + 1, to_find) == (expect_match ? &val : &val + 1)); } template TEST_CONSTEXPR_CXX20 void operator()() { test(0, 0); test(0, 1); test(1, 1); test(0, -1); test(-1, -1); test(0, U(-127)); test(T(-127), U(-127)); test(T(-128), U(-128)); test(T(-129), U(-129)); test(T(255), U(255)); test(T(256), U(256)); test(T(257), U(257)); test(0, std::numeric_limits::min()); test(T(std::numeric_limits::min()), std::numeric_limits::min()); test(0, std::numeric_limits::min() + 1); test(T(std::numeric_limits::min() + 1), std::numeric_limits::min() + 1); test(0, std::numeric_limits::max()); test(T(std::numeric_limits::max()), std::numeric_limits::max()); test(T(std::numeric_limits::max() - 1), std::numeric_limits::max() - 1); } }; struct TestIntegerPromotions { template TEST_CONSTEXPR_CXX20 void operator()() { types::for_each(types::integral_types(), TestIntegerPromotions1()); } }; TEST_CONSTEXPR_CXX20 bool test() { types::for_each(types::integer_types(), TestTypes()); types::for_each(types::integer_types(), TestTypes()); types::for_each(types::integer_types(), TestTypes()); #if TEST_STD_VER >= 20 Test, TriviallyComparable>().operator()*>(); Test, TriviallyComparable>().operator()*>(); #endif // TODO: Remove the `_LIBCPP_ENABLE_EXPERIMENTAL` check once we have the FTM guarded or views::join isn't // experimental anymore #if TEST_STD_VER >= 20 && (!defined(_LIBCPP_VERSION) || defined(_LIBCPP_ENABLE_EXPERIMENTAL)) { std::vector> vec = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; auto view = vec | std::views::join; assert(std::find(view.begin(), view.end(), 4) == std::next(view.begin(), 3)); } #endif types::for_each(types::integral_types(), TestIntegerPromotions()); return true; } int main(int, char**) { test_deque(); test(); #if TEST_STD_VER >= 20 static_assert(test()); #endif Test, Comparable >().operator()*>(); Test, Comparable >().operator()*>(); return 0; }