2011-11-17 12 views
14

Gli algoritmi STL standalone (come std::count_if) accettano una coppia di iteratori. In tutti i casi in cui io uso quelli (e in tutti gli esempi che ho visto in linea!), Mi ritrovo a digitareAlgoritmi STL che prendono l'intero contenitore anziché .begin(), end() come arg?

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

C'è un motivo per cui i modelli stenografici dello stile

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

non sono fornito, dato che più che non è l'operazione eseguita sull'intero contenitore? L'ho semplicemente trascurato? La risposta è diversa per C++ 11 e C++ 03?

+2

È semplicemente una decisione di progettazione. Molte persone non lo trovano una buona scelta (vedi http://www.slideshare.net/rawwell/iteratorsmustgo). Boost fornisce quegli algoritmi che usano i loro concetti di intervallo. – visitor

risposta

10

C'è una bella blog-post da Herb Sutter discutendo la questione . L'essenziale è che l'aggiunta di sovraccarichi basati su container per gli algoritmi può creare ambiguità se esiste già un sovraccarico per quell'algoritmo con lo stesso numero di parametri-modello. I concetti erano destinati a risolvere quel problema.

+0

Ok, quindi 'std :: count_if_all' o' std :: count_all_if' farebbe il lavoro? Lo stesso con 'std :: sort' (' std :: sort_all') e tutti gli altri ... –

0

Semplicemente perché gli algoritmi STL sono collegati/parla con il contenitore usando gli iteratori.

2

Una ragione potrebbe essere fornire la flessibilità per intervallo di iteratore. Potrebbe non essere necessario per scorrere tutti gli elementi a volte:

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

Inoltre, si può sempre avere un wrapper che fa questo per voi:

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

In C++ 11, usate 'begin (myContainer)' e 'end (myContainer)' per farlo funzionare anche con gli array. – Sjoerd

+1

Lo 0.1% -case in cui è necessario iterare solo su una parte del contenitore giustifica la digitazione di '.begin()' e '.end()' nei casi del 99,9%, se è possibile averli entrambi. – eudoxos

+1

@Euxodos: Sì, lo 0,1% dei casi sarebbe banalmente risolto con 'count_if (make_range (it, myContainer.end()), /*...*/);'. - Storicamente sembra che gli algoritmi siano stati aggiunti alla libreria standard in fretta, e gli iteratori sono stati un'idea così innovativa alla volta. Se avessero avuto un po 'più di esperienza con loro, le cose sarebbero potute essere diverse. Ma ora sembra che non possano lasciare andare le cose vecchie e non possono aggiungere nuove cose, a meno che non possano essere fatte in modo pulito. – UncleBens

2

Il principio e la flessibilità di STL sono principalmente dovuti al funzionamento su iteratori anziché contenitori. Non è un grosso problema, puoi riutilizzare il trucco che sto usando dai miei primi anni C:

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

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

In realtà è un trucco intelligente, anche se probabilmente lo chiamerei ALL e al giorno d'oggi uso std :: begin e std :: end –

Problemi correlati