| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- // 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 <concepts>
- #include <type_traits>
- #include "llvm/ADT/STLExtras.h"
- namespace Carbon {
- namespace Internal {
- template <typename Range>
- using RangePointerType = typename std::iterator_traits<decltype(std::begin(
- std::declval<Range>()))>::pointer;
- template <typename Range>
- using RangeValueType = typename std::iterator_traits<decltype(std::begin(
- std::declval<Range>()))>::value_type;
- template <typename Range, typename Pred>
- concept IsValidFindPredicate =
- requires(const RangeValueType<Range>& elem, Pred pred) {
- { pred(elem) } -> std::convertible_to<bool>;
- };
- template <typename A, typename B>
- concept IsComparable = requires(const A& a, const B& b) {
- { a == b } -> std::convertible_to<bool>;
- };
- template <typename Range>
- concept RangeValueHasNoneType = requires {
- { RangeValueType<Range>::None } -> std::convertible_to<RangeValueType<Range>>;
- };
- } // 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 <typename Range, typename Pred>
- requires Internal::IsValidFindPredicate<Range, Pred>
- constexpr auto FindIfOrNull(Range&& range, Pred predicate)
- -> Internal::RangePointerType<Range> {
- 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 <typename Range, typename Pred>
- requires Internal::IsValidFindPredicate<Range, Pred> &&
- Internal::RangeValueHasNoneType<Range> &&
- std::copy_constructible<Internal::RangeValueType<Range>>
- constexpr auto FindIfOrNone(Range&& range, Pred predicate)
- -> Internal::RangeValueType<Range> {
- auto it = llvm::find_if(range, predicate);
- if (it != range.end()) {
- return *it;
- } else {
- return Internal::RangeValueType<Range>::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 <typename Range, typename Query = Internal::RangeValueType<Range>>
- requires Internal::IsComparable<Query, Internal::RangeValueType<Range>>
- constexpr auto Contains(Range&& range, const Query& query) -> bool {
- return llvm::find(range, query) != range.end();
- }
- } // namespace Carbon
- #endif // CARBON_COMMON_FIND_H_
|