2011-11-17 5 views
14

Algoritmos STL independientes (como std::count_if) toman un par de iteradores. En todos los casos en los que uso (y en todos los ejemplos que he visto en línea!), Me encuentro escribiendoAlgoritmos STL tomando el contenedor completo en lugar de .begin(), end() como arg?

std::count_if(myContainer.begin(),myContainer.end(), /* ... */); 

¿Hay una razón por la cual las plantillas de la taquigrafía del estilo

std::count_if(myContainer, /* ... */); 

no son siempre que, dado que más de que no es la operación realizada en todo el contenedor? ¿Simplemente lo pasé por alto? ¿La respuesta es diferente para C++ 11 y C++ 03?

+2

Es simplemente una decisión de diseño. A muchas personas no les parece una buena opción (ver http://www.slideshare.net/rawwell/iteratorsmustgo). Boost proporciona esos algoritmos usando sus conceptos de Rango. – visitor

Respuesta

10

hay un bonito blog-post por Herb Sutter discutir la cuestión . Lo esencial es que la adición de sobrecargas basadas en contenedores para algoritmos puede crear ambigüedades si ya existe una sobrecarga para ese algoritmo con el mismo número de parámetros de plantilla. Los conceptos estaban destinados a solucionar ese problema.

+0

Ok, entonces 'std :: count_if_all' o' std :: count_all_if' harían el trabajo? Lo mismo con 'std :: sort' (' std :: sort_all') y todos los demás ... –

0

Simplemente porque los algoritmos STL están conectados/hablan con el contenedor mediante iteradores.

2

Una razón podría ser para proporcionar la flexibilidad para la gama de iteradores. Puede que no necesite para recorrer todos los elementos en algún momento:

<iterator> it = myContainer.begin(); 
it++; // do something 
it++; // do something 
... 
std::count_if(it, myContainer.end(), /* ... */); 

Además, siempre se puede tener una envoltura que lo hace por usted:

template<typename T> 
... count_if (T myContainer, ...) 
{ 
    std::count_if(myContainer.begin(), myContainer.end(), /* ... */); 
} 
+2

En C++ 11, use 'begin (myContainer)' y 'end (myContainer)' para que funcione también con las matrices. – Sjoerd

+1

El 0.1% -case donde necesita iterar solo sobre una parte del contenedor justifica escribir '.begin()' y '.end()' en el 99.9% de los casos, si es posible tener ambos. – eudoxos

+1

@Euxodos: Sí, esos 0.1% de casos se resolverían trivialmente con 'count_if (make_range (it, myContainer.end()), /*...*/);'. - Históricamente parece que los algoritmos se agregaron a la biblioteca estándar a toda prisa, y los iteradores eran una idea tan novedosa a la vez. Si hubieran tenido un poco más de experiencia con ellos, las cosas podrían haber resultado diferentes. Pero ahora parece que no pueden dejar de lado las cosas viejas y no pueden agregar cosas nuevas, a menos que se pueda hacer limpiamente. – UncleBens

2

El principio y la flexibilidad de STL se deben principalmente a que funcionan en iteradores en lugar de en contenedores. No es un gran problema, puede volver a utilizar el truco que estoy usando desde mis primeros años C:

#define FULL_RANGE(c) (c).begin(), (c).end() 

std::copy(FULL_RANGE(c), std::ostream_iterator<c::value_type>(cout, "\n")); 
+0

Es un truco inteligente en realidad, aunque probablemente lo llamaría TODO y en la actualidad uso std :: begin y std :: end –

Cuestiones relacionadas