sort pairs ejemplo c++ stl std design-rationale

c++ - pairs - ¿Por qué la biblioteca estándar tiene find y find_if?



vector c++ (4)

Ciertamente puede implementar find en términos de find_if usando algún tipo de predicado de igualdad.

Supongo que la verdadera razón es que puede implementar find bastante fácilmente y proporcionar implementaciones especializadas eficientes para tipos típicos encontrados; si está utilizando find_if , el predicado que pase puede ser arbitrariamente complejo, lo que le da al implementador de la biblioteca un menor alcance de optimización.

Además, C ++ tiene la filosofía de "no pagas por lo que no usas" y normalmente esperarías que no pagues por una evaluación de predicados si lo harías con una simple comparación.

No se pudo find_if solo fuera una sobrecarga de find ? Así es como std::binary_search y amigos lo hacen ...


No puede tener el mismo nombre porque habría una ambigüedad. Supongamos que tenemos una sobrecarga de find lugar de find_if . Entonces supongamos:

// Pseudo-code struct finder { bool operator()(const T&) const { ... } bool operator==(const finder& right) const { ... } } std::vector<finder> finders; finder my_finder; std::find(finders.begin(), finders.end(), my_finder);

El find no tendría forma de resolver la incoherencia: ¿debería intentar encontrar el finder en el contenedor o usar el finder para realizar la operación de búsqueda? Para resolver este problema, crearon dos nombres de funciones.


Un predicado es algo válido de encontrar, por lo que podría llegar a ambigüedades.

Considera find_if se renombra el find , entonces tienes:

template <typename InputIterator, typename T> InputIterator find(InputIterator first, InputIterator last, const T& value); template <typename InputIterator, typename Predicate> InputIterator find(InputIterator first, InputIterator last, Predicate pred);

Qué se debe hacer, entonces, con:

find(c.begin(), c.end(), x); // am I finding x, or using x to find?

En lugar de tratar de encontrar una solución intrincada para diferenciar basada en x (que no siempre se puede hacer *), es más fácil separarlos.

* Esto sería ambiguo, no importa cuál sea su esquema o cuán poderoso pueda ser †:

struct foo { template <typename T> bool operator()(const T&); }; bool operator==(const foo&, const foo&); std::vector<foo> v = /* ... */; foo f = /* ... */; // f can be used both as a value and as a predicate find(v.begin(), v.end(), f);

† Guarda la lectura mental.


Esto es lo que Stroustrup dijo (The C ++ Programming Language, 18.5.2):

Si find() y find_if() tuvieran el mismo nombre, habrían resultado aberraciones sorprendentes. En general, el sufijo _if se usa para indicar que un alrigma toma un predicado.

En cuanto a qué es exactamente esa "ambigüedad", Steve Jessop respondió eso en su respuesta (mejor calificada) a esta pregunta SO .

(nota: esa pregunta en realidad puede calificar como la misma pregunta que esta. No soy lo suficientemente inteligente en C ++ arcania para decidir).