// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef CARBON_COMMON_FIND_H_ #define CARBON_COMMON_FIND_H_ #include #include #include "llvm/ADT/STLExtras.h" namespace Carbon { namespace Internal { template using RangePointerType = typename std::iterator_traits()))>::pointer; template using RangeValueType = typename std::iterator_traits()))>::value_type; template concept IsValidFindPredicate = requires(const RangeValueType& elem, Pred pred) { { pred(elem) } -> std::convertible_to; }; template concept IsComparable = requires(const A& a, const B& b) { { a == b } -> std::convertible_to; }; template concept RangeValueHasNoneType = requires { { RangeValueType::None } -> std::convertible_to>; }; } // namespace Internal // Finds a value in the given `range` by testing the `predicate`. Returns a // pointer to the value from the range on success, and nullptr if nothing is // found. // // This is similar to `std::find_if()` but returns a pointer to the value // instead of an iterator that must be tested against `end()`. template requires Internal::IsValidFindPredicate constexpr auto FindIfOrNull(Range&& range, Pred predicate) -> Internal::RangePointerType { auto it = llvm::find_if(range, predicate); if (it != range.end()) { return std::addressof(*it); } else { return nullptr; } } // Finds a value in the given `range` by testing the `predicate` and returns a // copy of it. If no match is found, returns `T::None` where the input range is // over values of type `T`. template requires Internal::IsValidFindPredicate && Internal::RangeValueHasNoneType && std::copy_constructible> constexpr auto FindIfOrNone(Range&& range, Pred predicate) -> Internal::RangeValueType { auto it = llvm::find_if(range, predicate); if (it != range.end()) { return *it; } else { return Internal::RangeValueType::None; } } // Finds a value in the given `range` by comparing to `query`. Returns a // pointer to the value from the range on success, and nullptr if nothing is // found. // // This is similar to `std::find_if()` but returns a pointer to the value // instead of an iterator that must be tested against `end()`. template > requires Internal::IsComparable> constexpr auto Contains(Range&& range, const Query& query) -> bool { return llvm::find(range, query) != range.end(); } } // namespace Carbon #endif // CARBON_COMMON_FIND_H_