2009-12-22 9 views
6

Piszę bibliotekę interfejsów, która umożliwia dostęp do zmiennych w tabelach (do teoretycznie nieskończonej głębokości) w obiekcie typu regula::State. Osiągam to przez przeciążanie operator[] w klasie, która następnie zwraca inną z tej samej klasy i ponownie wywołuje operator[] w razie potrzeby. Na przykład:Dlaczego g ++ mówi "nie pasuje do" operatora = ', gdy wyraźnie jest, a Visual Studio widzi, że jest?

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

Powyższe ma miejsce wartość 3.14159 wewnątrz zmiennej pi w tabeli math. Zasadniczo robi to poprzez polecenie, że t zwraca obiekt proxy reprezentujący math, który zwraca inny obiekt proxy reprezentujący pi, do którego faktycznie zapisujemy zmienną. Wewnętrzne tego nie są naprawdę istotne dla pytania, ale tutaj jest nagłówek funkcji.

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

Zasadniczo, w powyższym przykładzie, program powinien nazywać t „s operator[] z ciągiem "math" i powrócić inny obiekt, a następnie nazwać obiektu operator[] z ciągiem "pi", która zwraca ostateczny cel, a następnie przypisuje wartość do tej wartości za pomocą operator=.

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

The T zwracany jest po prostu kopią value minął.

Teraz mój kod nie generuje żadnych błędów w Visual C++ 2008 i działa idealnie. Ale gdy próbuję skompilować go na Linuksie z g++, pojawia się następujący błąd:

../../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&) 

Z jakiegoś powodu, g++ wydaje się próby wywołania operator= na operator[], ignorując zwróconego obiektu jak to ma być.

faktycznie mogę naprawić ten błąd, zastępując typ zwracany na operator= z void:

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

Ale to nie jest korzystne, a poza tym mam podobne błędy w kilku innych miejscach z podobnie przeciążony 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>())))))’ 

Nie rozumiem, dlaczego ten błąd występuje w g ++, lub dlaczego nie występuje w Visual C++. Czy ktoś może rzucić na to jakiekolwiek światło lub zalecić jakieś rozwiązania?

+4

prawdziwy kod pocztowy. Twoje próbki są zepsute. 'regula :: State t [" math "] [" pi "] = 3.14159;' nie może być poprawną instrukcją C++. "Naprawiona" deklaracja 'operatora =' również jest zepsuta, ponieważ teraz nie ma "T" tam – AnT

+0

@AndreyT: Przepraszam, ta linia została obcięta, gdy nie powinna. Naprawiłem próbkę, o której mowa. – pdusen

+2

Czy umiesz go sprowadzić do małego fragmentu, który demonstruje błąd? – Eclipse

Odpowiedz

6

Sekcja 5.17 normy ISO mówi

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.

swoje operator= powraca nie tylko niewłaściwy typ, ale nawet nie lwartością. Zakładając, że komunikat o błędzie GCC nie zawiera żadnych innych kandydatów oprócz operator=(const regula::LObject&), GCC po prostu całkowicie zignorowało twoje przeciążenie. Wymieniona nazwa operator= jest domyślną, automatycznie generowaną funkcją.

Na drugi rzut oka, twój operator[] również powinien zwrócić referencję. Jak napisano, żadne wyrażenia przydziału, takie jak przykład, nie powinny w ogóle działać.

Tak, trzeba mieć funkcje

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

i

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

To prawda, że ​​sposób, w jaki operator = jest zadeklarowany, jest nieprawidłowy, niekoniecznie jest prawdą, że operator [] jest uznany za nieprawidłowy. W rzeczywistości specjalizacja dla ':: std :: vector ' definiuje operator [] do zwracania _Bit_reference (nie rzeczywistego odniesienia). _Bit_reference z kolei jest klasą, która definiuje własną '_Bit_reference & _Bit_reference :: operator = (bool x)'. – Omnifarious

+0

Jego operator [] jest ważny; operator [] nie jest zobowiązany do zwrócenia wartości l we wszystkich momentach, o ile pamiętam (nie sprawdzając tego teraz). Chodzi o to, że używa * go jako lwartości. – Potatoswatter

+0

Cóż, wynik ':: std :: vector :: operator []' jest również przeznaczony do użycia jako l-wartości i zwraca tymczasowy, tak jak on. – Omnifarious

Powiązane problemy