2009-12-22 7 views
6

Sto scrivendo una libreria di interfaccia che consente l'accesso a variabili all'interno di tabelle (fino ad una profondità teoricamente infinita) in un oggetto di tipo regula::State. Lo sto facendo sovraccaricando operator[] all'interno di una classe, che poi ne restituisce un altro di quella stessa classe e chiama di nuovo operator[] come necessario. Ad esempio:Perché g ++ dice 'nessuna corrispondenza per' operator = 'quando c'è chiaramente, e Visual Studio può vedere che c'è?

regula::State t; 
t["math"]["pi"] = 3.14159; 

Quanto sopra è supposto per posizionare il valore 3.14159 raggio variabile pi nella tabella math. Fondamentalmente, lo fa avere t restituire un oggetto proxy che rappresenta math, che restituisce un altro oggetto proxy che rappresenta pi, a cui in realtà salviamo la variabile. Gli interni di questo non sono veramente rilevanti per la domanda, ma qui c'è l'intestazione della funzione.

LObject LObject::operator[] (const std::string name); 

Fondamentalmente, nell'esempio di cui sopra, il programma dovrebbe chiamare t s' operator[] con la stringa "math" e restituire un altro oggetto, e quindi chiamare l'oggetto di operator[] con la stringa "pi", che restituisce l'oggetto finale, e poi assegna il valore a quello usando operator=.

template <typename T> 
T LObject::operator= (const T& value); 

Il T restituito è solo una copia del value passato.

Ora, il mio codice non produce errori in Visual C++ 2008 e funziona perfettamente. Ma quando provo a compilare su Linux con g++, ottengo il seguente errore:

../../test/regula-test.cpp:100: error: no match for ‘operator=’ in 
‘L.regula::State::operator[](std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >(((const char*)"Numbers"), ((const std::allocator<char>&)((const 
std::allocator<char>*)(& std::allocator<char>()))))) = Numbers’ 
../../include/regula.hpp:855: note: candidates are: regula::LObject& 
regula::LObject::operator=(const regula::LObject&) 

Per qualche ragione, g++ sembra essere cercando di chiamare operator= su operator[], piuttosto che l'oggetto restituito come si suppone essere.

posso effettivamente risolvere questo errore sostituendo il tipo di ritorno su operator= con void:

template <typename T> 
/*T*/ void LObject::operator= (const T& value); 

ma questo non è preferibile, ed inoltre, ho errori simili in diverse altre posizioni con un altrettanto sovraccarico operator==:

../../test/regula-test.cpp:153: error: no match for ‘operator==’ in ‘pi == 
L.regula::State::operator[](std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >(((const char*)"pi"), ((const std::allocator<char>&)((const 
std::allocator<char>*)(& std::allocator<char>())))))’ 

non capisco perché questo errore si verifica in g ++, o perché non si sta verificando in Visual C++. Qualcuno può far luce su questo o consigliare qualche soluzione?

+4

postale vero e proprio codice. I tuoi campioni sono rotti 'regula :: State t [" math "] [" pi "] = 3.14159;' non può essere un'istruzione C++ valida. Anche la dichiarazione "fissa" del tuo operatore = 'è rotta, perché ora non c'è il' T' lì – AnT

+0

@AndreyT: Mi scuso, quella riga è stata troncata quando non avrebbe dovuto essere. Ho risolto il campione in questione. – pdusen

+2

Puoi ridurlo a un piccolo snippet che mostra l'errore? – Eclipse

risposta

6

sezione 5.17 dello standard ISO dice

There are several assignment operators, all of which group right-to-left. All require a modifiable lvalue as their left operand, and the type of an assignment expression is that of its left operand. The result of the assignment operation is the value stored in the left operand after the assignment has taken place; the result is an lvalue.

vostri operator= restituisce non solo il tipo sbagliato, ma nemmeno un lvalue. Supponendo che il messaggio di errore di GCC non includesse altri candidati oltre allo operator=(const regula::LObject&), GCC ha semplicemente ignorato completamente il sovraccarico. Il numero operator= menziona è la funzione predefinita generata automaticamente.

A prima vista, il tuo operator[] dovrebbe anche restituire un riferimento. Come scritto, nessuna espressione di assegnazione come il tuo esempio dovrebbe funzionare affatto.

Quindi, si dovrebbe avere funzioni

LObject &LObject::operator[] (const std::string name); 

e

template <typename T> 
LObject &LObject::operator= (const T& value); 
+0

Beh, è ​​vero che il modo in cui operator = è dichiarato è sbagliato, non è necessariamente vero che l'operatore [] è dichiarato errato. In effetti, la specializzazione per ':: std :: vector ' definisce operator [] per restituire _Bit_reference (non un riferimento reale). _Bit_reference a sua volta è una classe che definisce il proprio '_Bit_reference & _Bit_reference :: operator = (bool x)'. – Omnifarious

+0

Il suo operatore [] è valido; operator [] non è tenuto a restituire un lvalue per quanto mi ricordo (non cercandolo ora). Il punto è, sta * usando * it come valore. – Potatoswatter

+0

Bene, il risultato di ':: std :: vector :: operator []' è pensato per essere usato anche come lvalue e restituisce un valore temporaneo come il suo. – Omnifarious

Problemi correlati