Commenti a: Modern range-based iteration https://www.italiancpp.org/2013/09/23/modern-range-based-iteration/ Mon, 20 Mar 2017 21:21:21 +0000 hourly 1 https://wordpress.org/?v=4.7.18 Di: marco https://www.italiancpp.org/2013/09/23/modern-range-based-iteration/#comment-47 Tue, 24 Sep 2013 08:13:06 +0000 http://www.italiancpp.org/?p=1201#comment-47 Ciao Luca, grazie dell’osservazione. Come dicevo all’inizio, essendo l’articolo basic ho solo accennato a questo genere di questioni, ma in ogni caso il tuo commento può costituire un punto d’inizio per tutti coloro che vogliono spingersi un po’ oltre (insieme, ad esempio, alla reference). Sicuramente spenderemo almeno un altro articolo su questioni più “avanzate”, come la tua proposta!

]]>
Di: Luca Risolia https://www.italiancpp.org/2013/09/23/modern-range-based-iteration/#comment-46 Mon, 23 Sep 2013 23:12:47 +0000 http://www.italiancpp.org/?p=1201#comment-46 Scusate se non concentro tutte le osservazioni in un’unica risposta, ma alcuni spunti di riflessione mi vengono in mente solo dopo una seconda rilettura.

Cito il seguente periodo dell’articolo:

“Comunque, l’idea fondamentale è che è necessario definire alcune funzioni anziché ereditare da una classe base. Qualsiasi classe che “si comporta” come un InputIterator è allora considerata un InputIterator.”

Mi trovo ovviamente d’accordo con la seconda affermazione. Per quanto riguarda la prima affermazione varrebbe spendere qualche parolina in più.

Al lettore più ingenuo, soprattutto, vorrei dire che lo standard, in realtà, definisce intenzionalmente la classe template std::iterator come classe base da cui si dovrebbe sempre ereditare, parametrizzandola in maniera opportuna, quando si implementa un iteratore.

std::iterator definisce solo tipi membro e viene “configurata” sulla base dei tipi di argomenti ad essa passati. I tipi così definiti servono ad un’altra classe template dello standard, std::iterator_traits (che prende come parametro il tipo iteratore *standard*), per determinare alcune proprietà degli iteratori, le quali possono servire alle implementazioni degli algoritmi generici dello standard. La particolarità di std::iterator_traits, infatti, è che è specializzata per gli iteratori che sono puntatori a elementi di tipo T, T* e const T* nello specifico: ciò consente di definire una sola implementazione di un dato algoritmo (vedi sotto per un esempio). E allo stesso modo l’utente può scrivere altri algoritmi generici *senza* bisogno di doverli specializzare per iteratori di tipo puntatore, sfruttando std::iterator_traits.

Un classico esempio è count(). Con interator_traits si può scrivere una sola volta:


template
typename iterator_traits::difference_type
count(In first, In last, const T& val) { /*...*/ }

Si può scrivere, cioè, un’implementazione valida anche quando l’iteratore è di tipo T* o const T*,perchè std::iterator_traits è specializzato per iteratori di tipo T* e const T* (quando In deriva da std::iterator appunto).

Al contrario, se non si usasse iterator_traits (o non si potesse usare perchè il proprio iteratore non è derivato opportunamente, come dicevo prima, da std::iterator), allora si sarebbe costretti a scrivere, per essere “veramente generici”, più implementazioni di count(), di cui una una specializzata per T*, per esempio:


template
typename In::difference_type count(In first, In last, const T& v);

template ptrdiff_t count(T* first, T* last, const T& v);

Se si devono scrivere molti algoritmi generici, si capisce bene il vantaggio della coppia std::iterator e std::iterator_traits.

Non vorrei aver dato un taglio “avanzato” alla discussione, ma direi che il prossimo spunto può essere quello di imparare a conoscere/riconoscere le varie categorie di iteratori per saper approfittare adeguatamente di std::interator e std::iterator_traits.

]]>
Di: Luca Risolia https://www.italiancpp.org/2013/09/23/modern-range-based-iteration/#comment-45 Mon, 23 Sep 2013 08:32:37 +0000 http://www.italiancpp.org/?p=1201#comment-45 Ciao Marco, si, era i < END. Grazie.

]]>
Di: marco https://www.italiancpp.org/2013/09/23/modern-range-based-iteration/#comment-44 Mon, 23 Sep 2013 08:29:22 +0000 http://www.italiancpp.org/?p=1201#comment-44 Ciao Luca, grazie a te del commento. Ti riferisci a i < END? Hai ragione e mi era sfuggito (ho corretto). Per il resto ho sempre messo l'operatore != (anche nell'esempio del range_it)!

]]>
Di: Luca Risolia https://www.italiancpp.org/2013/09/23/modern-range-based-iteration/#comment-43 Mon, 23 Sep 2013 08:24:31 +0000 http://www.italiancpp.org/?p=1201#comment-43 Ciao Marco, grazie per l’articolo.

In realtà, quando parli di idioma spesso usato per scorrere una sequenza mediante un InputIterator, si dovrebbe preferire operator!=() come condizione di terminazione del ciclo, anzichè operator<(). La nota è sostanziale, proprio perchè gli InputIterator (oggetto del discorso) non devono definire necessariamente un ordinamento.

]]>