2011-12-16 16 views
9

Sto scrivendo un sottile involucro modello per iteratori, e ha colpito un ostacolo quando passa attraverso l'operatore struttura dereferenziazione, soprattutto perché i puntatori non hanno uno:Struttura operatore dereference (operator->)

#include <vector> 

struct mystruct { 
    int member; 
}; 

template<class iterator> 
struct wrap { 
    typedef typename std::iterator_traits<iterator>::pointer pointer; 
    iterator internal; 
    pointer operator->() {return internal.operator->();} //MARK1 
}; 

int main() { 
    wrap<std::vector<mystruct>::iterator> a; 
    a->member; 
    wrap<mystruct*> b; 
    b->member; 
    return 0; 
} 

http://ideone.com/XdvEz

prog.cpp: In member function ‘typename std::iterator_traits<_Iter>::pointer wrap<iterator>::operator->() [with iterator = mystruct*]’: 
prog.cpp:18: instantiated from here 
prog.cpp:11: error: request for member ‘operator->’ in ‘((wrap<mystruct*>*)this)->wrap<mystruct*>::internal’, which is of non-class type ‘mystruct*’ 

Questo seguente metodo funziona, ma non credo che è garantito il funzionamento. Vale a dire, se un iteratore ha uno strano tipo pointer che non è uguale a un puntatore a un value_type.

pointer operator->() {return &*internal;} //MARK3 
+1

Quale versione di C++ ha una struttura * * operatore dereferenziazione? –

+0

Perché 'char *'? Non ci sarebbe una sorta di 'Iterator :: value_type' da qualche parte? –

+3

@ThomasMatthews: Questo è ciò che [wikipedia] (http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Member_and_pointer_operators) chiama. Lo standard C++ lo chiama semplicemente 'operator->'. –

risposta

10

Lo standard indirettamente dice che un sovraccarico operator-> deve restituire un puntatore, un oggetto che è convertibile ad un puntatore, o di un oggetto che ha sovraccaricato operator->. La soluzione migliore è semplicemente restituire internal.

§13.5.6 [over.ref] p1

Un'espressione x->m viene interpretato come (x.operator->())->m

(Quanto sopra vale in modo ricorsivo.)

+0

E prima di chiedere su 'operator *()', il tipo restituito è 'iterator_traits :: reference' e restituisce solo' * iterator'. Qualsiasi iteratore che non restituisca un 'reference' sulla dereferenziazione non modella correttamente il concetto di iteratore e può essere ignorato con cura. – Xeo

+0

Sì, ho avuto l'operatore * ', ma non mi è mai venuto in mente di restituire un' iteratore' invece di un 'puntatore'. Grazie! Mi aspetto che questa sia la risposta, ma cercherò di dargli un giorno o due per altri suggerimenti. –

+0

Vorrei solo aggiungere che la ricorsione termina quando viene restituito un puntatore (o un oggetto convertibile in un puntatore), quindi se operatore-> restituisce un puntatore hai colpito il caso base di ricorsione e il gioco è fatto. Se operator-> restituisce qualcos'altro con un operatore-> sovraccarico, allora ricorri. Questo può sembrare ovvio, ma mi ci è voluto un po 'per risolverlo. –