std::ranges::search
De cppreference.com
<tbody>
</tbody>
| 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:
- Las listas de argumentos de plantilla explícitas no se pueden especificar al llamar a cualquiera de ellas.
- Ninguna de ellas es visible para la búsqueda dependiente de argumentos.
- Cuando alguna de ellas se encuentra mediante la búsqueda normal no calificada como el nombre a la izquierda del operador de llamada a función, se inhibe la búsqueda dependiente de argumentos.
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}.
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
Ejecuta este código
#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
(C++20) |
Encuentra dos primeros elementos contiguos idénticos (o que satisfagan un predicado dado). (niebloid) |
(C++20)(C++20)(C++20) |
Encuentra el primer elemento que satisfaga un criterio específico. (niebloid) |
(C++20) |
Encuentra la última secuencia de elementos en un cierto rango. (niebloid) |
(C++20) |
Busca por cualquiera de un conjunto de elementos. (niebloid) |
(C++23)(C++23) |
Comprueba si el rango contiene el elemento dado o un subrango. (niebloid) |
(C++20) |
Devuelve true si una secuencia es una subsecuencia de otra. (niebloid) |
(C++20) |
Encuentra la primera posición donde dos rangos difieren. (niebloid) |
(C++20) |
Busca un número de copias consecutivas de un elemento en un rango. (niebloid) |
| Busca una subsecuencia de elementos. (plantilla de función) |