◐ Shell
clean mode source ↗

std::ranges::search - cppreference.com

De cppreference.com

Definido en el archivo de encabezado <algorithm>

Signatura de la llamada

template< std::forward_iterator I1, std::sentinel_for<I1> S1, std::forward_iterator I2, std::sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = std::identity, class Proj2 = std::identity > requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr ranges::subrange<I1> search( I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );

(1) (desde C++20)

template< ranges::forward_range R1, ranges::forward_range R2, class Pred = ranges::equal_to, class Proj1 = std::identity, class Proj2 = std::identity> requires std::indirectly_comparable<ranges::iterator_t<R1>, ranges::iterator_t<R2>, Pred, Proj1, Proj2> constexpr ranges::borrowed_subrange_t<R1> search( R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );

(2) (desde C++20)

1) Busca la first ocurrencia de la secuencia de elementos [first2, last2) en el rango [first1, last1). Los elementos se comparan usando el predicado binario pred después de proyectarse con proj2 y proj1, respectivamente.

2) Igual que (1), pero usa r1 como el primer rango fuente y r2 como el segundo rango fuente, como si usara ranges::begin(r1) como first1, ranges::end(r1) como last1, ranges::begin(r2) como first2, y ranges::end(r2) como last2.

Las entidades similares a funciones descritas en esta página son niebloids, es decir:

En la práctica, pueden implementarse como objetos función o con extensiones de compilador especiales.

Parámetros

first1, last1 - El rango de elementos a examinar (alias pajar).
first2, last2 - El rango de la secuencia de elementos a buscar (alias aguja).
r1 - El rango de elementos a examinar (alias pajar).
r2 - El rango de la secuencia de elementos a buscar (alias aguja).
pred - El predicado binario a aplicar a los elementos proyectados.
proj1 - Proyección a aplicar a los elementos en el primer rango.
proj2 - Proyección a aplicar a los elementos en el segundo rango.

Valor de retorno

1) Devuelve un valor de tipo ranges::subrange que es la primera ocurrencia de la secuencia [first2, last2) (alias aguja) en el rango [first1, last1) (alias pajar), después de la aplicación de las proyecciones proj1 y proj2 a los elementos de ambas secuencias, respectivamente con la consiguiente aplicación del predicado binario pred para comparar los elementos proyectados.

Si no se encuentra tal ocurrencia, se devuelve ranges::subrange{last1, last1}.

Si el rango a buscar (alias aguja) está vacío, es decir first2 == last2, entonces se devuelve ranges::subrange{first1, first1}.

2) Igual que (1) pero el tipo de retorno es ranges::borrowed_subrange_t<R1>.

Complejidad

A lo sumo S*N aplicaciones del predicado correspondiente y cada proyección, donde
(1) S = ranges::distance(first2, last2) y N = ranges::distance(first1, last1);
(2) S = ranges::distance(r2) y N = ranges::distance(r1).

Posible implementación

struct search_fn
{
  template<std::forward_iterator I1, std::sentinel_for<I1> S1,
         std::forward_iterator I2, std::sentinel_for<I2> S2,
         class Pred = ranges::equal_to,
         class Proj1 = std::identity,
         class Proj2 = std::identity>
  requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
  constexpr ranges::subrange<I1>
    operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
               Proj1 proj1 = {}, Proj2 proj2 = {}) const {
        for (;; ++first1) {
          I1 it1 = first1;
          for (I2 it2 = first2;; ++it1, ++it2) {
            if (it2 == last2) return {first1, it1};
            if (it1 == last1) return {it1, it1};
            if (!std::invoke(pred, std::invoke(proj1, *it1), std::invoke(proj2, *it2)))
              break;
          }
        }
    }

  template<ranges::forward_range R1, ranges::forward_range R2,
         class Pred = ranges::equal_to,
         class Proj1 = std::identity,
         class Proj2 = std::identity>
  requires std::indirectly_comparable<ranges::iterator_t<R1>,
                                      ranges::iterator_t<R2>, Pred, Proj1, Proj2>
  constexpr ranges::borrowed_subrange_t<R1>
    operator()(R1&& r1, R2&& r2, Pred pred = {},
               Proj1 proj1 = {}, Proj2 proj2 = {}) const {
      return (*this)(ranges::begin(r1), ranges::end(r1),
                     ranges::begin(r2), ranges::end(r2),
                     std::move(pred), std::move(proj1), std::move(proj2));
    }
};

inline constexpr search_fn search{};

Ejemplo

#include <algorithm>
#include <cctype>
#include <iostream>
#include <iterator>
#include <string_view>

using namespace std::literals;

void imprimir(int id, const auto& pajar, const auto& aguja, const auto& encontrado) {
    std::cout << id << "). search(\"" << pajar << "\", \"" << aguja << "\"); ";
    const auto first = std::distance(pajar.begin(), encontrado.begin());
    const auto last = std::distance(pajar.begin(), encontrado.end());
    if (encontrado.empty()) {
        std::cout << "no se encontró;";
    } else {
        std::cout << "se encontró: \"";
        for (const auto x: encontrado) { std::cout << x; }
        std::cout << "\";";
    }
    std::cout << " subrango: {" << first << ", " << last << "}\n";
}

int main()
{
    constexpr auto pajar {"abcd abcd"sv};
    constexpr auto aguja {"bcd"sv};

    // la búsqueda usa el par de iteradores begin()/end():
    constexpr auto encontrado1 = std::ranges::search(
        pajar.begin(), pajar.end(),
        aguja.begin(), aguja.end());
    imprimir(1, pajar, aguja, encontrado1);

    // la búsqueda usa los rangos r1, r2:
    constexpr auto encontrado2 = std::ranges::search(pajar, aguja);
    imprimir(2, pajar, aguja, encontrado2);

    // el rango 'aguja' está vacío:
    constexpr auto nada {""sv};
    constexpr auto encontrado3 = std::ranges::search(pajar, nada);
    imprimir(3, pajar, nada, encontrado3);

    // 'aguja' no se encontrará:
    constexpr auto punzon1 {"efg"sv};
    constexpr auto encontrado4 = std::ranges::search(pajar, punzon1);
    imprimir(4, pajar, punzon1, encontrado4);

    // la búsqueda usa el comparador personalizado y proyecciones:
    constexpr auto punzon2 {"234"sv};
    auto encontrado5 = std::ranges::search(pajar, punzon2,
        [](const int x, const int y) { return x == y; }, // pred
        [](const int x) { return std::toupper(x); }, // proj1
        [](const int y) { return y + 'A' - '1'; } // proj2
        );
    imprimir(5, pajar, punzon2, encontrado5);
}

Salida:

1). search("abcd abcd", "bcd"); se encontró: "bcd"; subrango: {1, 4}
2). search("abcd abcd", "bcd"); se encontró: "bcd"; subrango: {1, 4}
3). search("abcd abcd", ""); no se encontró; subrango: {0, 0}
4). search("abcd abcd", "efg"); no se encontró; subrango: {9, 9}
5). search("abcd abcd", "234"); se encontró: "bcd"; subrango: {1, 4}

Véase también

Encuentra dos primeros elementos contiguos idénticos (o que satisfagan un predicado dado).
(niebloid) [editar]
Encuentra el primer elemento que satisfaga un criterio específico.
(niebloid) [editar]
Encuentra la última secuencia de elementos en un cierto rango.
(niebloid) [editar]
Busca por cualquiera de un conjunto de elementos.
(niebloid) [editar]
Comprueba si el rango contiene el elemento dado o un subrango.
(niebloid) [editar]
Devuelve true si una secuencia es una subsecuencia de otra.
(niebloid) [editar]
Encuentra la primera posición donde dos rangos difieren.
(niebloid) [editar]
Busca un número de copias consecutivas de un elemento en un rango.
(niebloid) [editar]
Busca una subsecuencia de elementos.
(plantilla de función) [editar]