2009-07-10 17 views
14

Ho una classeÈ possibile ottenere il tipo di valore da un iteratore arbitrario (C++)?

template <typename Iterator, typename Value> 
class Foo { 
public: 
    Foo(const Iterator& it) { ... } 
    ... 
private: 
    map<Value, int> m_; 
    } 
}; 

C'è un modo per sbarazzarsi di valore nel modello? L'Iterator può o non può essere un iteratore STL, ma è garantito che * digita il valore.

So di iterator_traits<T>::value_type per gli iteratori STL, ma mi chiedo se c'è un modo per ottenere automaticamente il tipo di valore per un tipo Iterator arbitrario?

Un trucco che sto pensando - per esempio, abbiamo una classe di supporto

template <typename Iterator, typename Value> 
class Bar { 
public: 
    Bar(const Iterator& dummy_iterator, const Value& dummmy_value) {} 
    ... 
}; 

Poi se istanziamo Bar come Bar (it, * esso), il tipo di valore sarà conosciuta all'interno Bar. Ma non riesco a trovare un buon modo per combinare Bar con Foo.

risposta

18

Qualsiasi iteratore deve fornire iterator_traits<Iterator>::value_type. In caso contrario, non è un iteratore. ISO C++ 2003 24.3.1 [lib.iterator.traits] "iterator_traits":

implementare algoritmi solo in termini di iteratori, è spesso necessario determinare il valore e la differenza tipi corrispondenti a un particolare tipo di iteratore . Di conseguenza, è necessario che se Iterator è il tipo di un iteratore, i tipi

iterator_traits<Iterator>::difference_type 
iterator_traits<Iterator>::value_type 
iterator_traits<Iterator>::iterator_category 

essere definito come tipo dell'iteratore differenza, tipo di valore e categoria iteratore, rispettivamente.

A parte questo, non esiste un modo generale per ottenere un tipo di espressione C++ arbitraria. C++ 0x lo correggerà fornendo decltype.

+0

Grazie, il riferimento alla norma ISO C++ è utile. –

1

spiacenti. Il modo corretto per sbarazzarsi di Value è quello di utilizzare iterator_traits come lei ha suggerito.

Se l'iteratore non STL è un puntatore nudo, poi si arriva iterator_traits corrette typedef gratuitamente. Altrimenti la classe di iteratore non STL deve definire i typedef corretti.

Vedere la iterator traits documentation per ulteriori informazioni.

1

Come per ottenere tipo di valore di iteratori risposte precedenti erano corrette.

Ma c'è di più. Il trucco a cui stai pensando non funzionerebbe con la classe. Se Bar era una funzione simile:

template <typename Iterator, typename Value> 
void bar(const Iterator& dummy_iterator, const Value& dummmy_value) {} 

poi tipo detrazione avrebbe funzionato per bar(it, *it) e si avrebbe il tipo di valore all'interno di bar. (Ma tieni presente che per usare questo trucco dovresti comunque avere un iteratore dereferenziabile che non è sempre buono - come gestire la sequenza vuota allora?)

Utilizzando una classe Bar sarebbe necessario fornire manualmente gli argomenti di template Iterator e Value in quanto non v'è alcun tipo di detrazione per le classi e l'utilizzo Bar(it, *it) non sarebbe compilazione.

+0

Grazie! Ho pensato la stessa cosa usando la barra in funzione, ma pensato che forse mi manca qualcosa. –

Problemi correlati