2010-10-19 13 views
20

La mia domanda è certa per chiunque abbia familiarità con la sintassi C++. Sto solo imparando C++ e questo è un po 'di tipo di compiti.Come recuperare il tipo di valore da iteratore in C++?

template<typename Iter> 
void quickSort(Iter begin, Iter end) 
{   
    //.. 
    auto pivot = * (begin + (end - begin)/2); 
    //.. 
} 

perno si suppone che contengono valore dal centro di [inizio, fine] intervallo. Ite Il codice che ho scritto lì funziona, ma auto è una parola chiave dal nuovo standard della lingua. Come si fa alla vecchia maniera? Cosa scrivere invece di auto?

+18

Questo è quello che mi piace vedere. Qualcuno che sta solo imparando C++, usando iteratori e 'auto'. :) – jalf

risposta

23

typename std::iterator_traits<Iter>::value_type

Questo funziona se il modello viene creata un'istanza con Iter come un tipo di puntatore.

A proposito, typename non fa parte del tipo stesso. Indica al compilatore che value_type è davvero un tipo. Se era il nome di una funzione o di un membro di dati statici, ciò influisce sulla sintassi. Il compilatore non sa necessariamente di cosa si tratta, dal momento che la specializzazione diper Iter potrebbe non essere visibile quando il modello è compilato.

+1

Questa è la migliore soluzione possibile, ma vale la pena sottolineare che non è una soluzione generale. Non è garantito che funzioni con tutto ciò che un utente potrebbe provare a passare come iteratore ... potrebbe comunque aver bisogno di aggiungere value_type al loro oggetto iteratore (o creare una specializzazione per i tratti). Un'alternativa è semplicemente quella di continuare a utilizzare gli iteratori e creare un iteratore nel pivot, dereferendolo come necessario, senza che sia necessario il tipo di valore all'interno della funzione basata su modello. –

+3

@Tony: è vero, e 'auto' è migliore per questo motivo. Tuttavia, tutti gli algoritmi standard richiedono all'utente di passare qualcosa che abbia 'iterator_traits' (24.3.1), ed è ragionevole che i modelli di funzioni definiti dall'utente abbiano la stessa restrizione. Le persone che scrivono gli iteratori possono usare 'std :: iterator' come una classe base per colmare il divario tra * provare * a passare un iteratore, e in realtà passare un' Iterator' ;-) –

+1

@Steve: sì, assolutamente (e hai già un +1 da me). –

1

La risposta di Steve è giusta; in C++ 98, devi usare std :: iterator_traits oppure puoi utilizzare Iter :: value_type se sai che l'iteratore ha questo typedef (ad es. deriva da std :: iterator). Tuttavia, c'è un altro problema nel codice: normalmente non puoi semplicemente dividere gli iteratori. Questo funziona con i puntatori, ovviamente, ma non nel caso più generale. Un approccio più generale sarebbe:

Iter itPivot = std::advance(begin, std::distance(begin, end)/2); 
+0

Il codice originale non divide gli iteratori e ciò non funzionerebbe, nemmeno con i puntatori. Il codice utilizza invece la sottrazione, che funziona su tutti gli iteratori di accesso casuale (non solo puntatori). E dato che quicksort sarà comunque ordinato per altri tipi di iteratore (comunque un'efficiente implementazione), l'uso di 'operator -' qui va bene. –

Problemi correlati