2009-12-22 10 views
6

Estoy escribiendo una biblioteca de interfaz que permite el acceso a variables dentro de tablas (hasta una profundidad teóricamente infinita) en un objeto de tipo regula::State. Estoy logrando esto sobrecargando operator[] dentro de una clase, que luego devuelve otra de la misma clase, y llamo a operator[] nuevamente según sea necesario. Por ejemplo:¿Por qué g ++ dice 'no concuerda con' operator = 'cuando claramente lo hay, y Visual Studio puede ver que hay?

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

Lo anterior se supone que coloque el valor de la variable dentro 3.14159pi en la tabla math. Básicamente, lo hace mediante t devuelve un objeto proxy que representa math, que devuelve otro objeto proxy que representa pi, al que realmente guardamos la variable. Las partes internas de esto no son realmente relevantes para la pregunta, pero aquí está el encabezado de la función.

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

Básicamente, en el ejemplo anterior, el programa debe llamar t 's operator[] con la cadena "math" y volver otro objeto, y luego llamar a ese objeto de operator[] con la cadena "pi", que devuelve el objeto final y, a continuación, asigna el valor a ese utilizando operator=.

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

El T devuelto es sólo una copia de la value pasado.

Ahora, mi código no produce errores en Visual C++ 2008 y funciona perfectamente. Pero cuando intento compilar en Linux con g++, me sale el siguiente error:

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

Por alguna razón, g++ parece estar tratando de llamar operator= en operator[], en lugar de en el objeto devuelto como se supone ser.

realmente puedo corregir este error mediante la sustitución del tipo de retorno de la operator= con void:

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

Pero esto no es preferible, y además, tener errores similares en varios otros lugares con una forma similar sobrecargado 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>())))))’ 

no entiendo por qué este error se produce en g ++, o por qué no se está produciendo en Visual C++. ¿Alguien puede arrojar algo de luz sobre esto o recomendar alguna solución?

+4

Código postal real. Sus muestras están rotas. 'regula :: State t [" math "] [" pi "] = 3.14159;' no puede ser una declaración de C++ válida. La declaración "fija" de su 'operator =' también está rota, porque ahora no hay 'T' allí – AnT

+0

@AndreyT: me disculpo, esa línea se truncó cuando no debería haber sido. He arreglado la muestra en cuestión. – pdusen

+2

¿Puedes reducirlo a un pequeño fragmento que demuestre el error? – Eclipse

Respuesta

6

Sección 5.17 de la norma 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.

Sus operator= vuelve no sólo el tipo equivocado, pero ni siquiera una lvalue. Suponiendo que el mensaje de error de GCC no incluyera ningún otro candidato además de operator=(const regula::LObject&), GCC simplemente ha ignorado su sobrecarga por completo. El operator= que menciona es la función predeterminada, generada automáticamente.

En segundo vistazo, su operator[] también debe devolver una referencia. Tal como está escrito, ninguna expresión de asignación como su ejemplo debería funcionar en absoluto.

lo tanto, debe tener funciones

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

y

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

Bueno, es cierto que la forma en que se declara operator = es incorrecta, no es necesariamente cierto que el operador [] se declare incorrecto. De hecho, la especialización para ':: std :: vector ' define operator [] para devolver una _Bit_reference (no una referencia real). _Bit_reference a su vez es una clase que define su propia '_Bit_reference & _Bit_reference :: operator = (bool x)'. – Omnifarious

+0

Su operador [] es válido; El operador [] no está obligado a devolver un lvalue por lo que recuerdo (sin buscarlo ahora). El punto es que está * usando * como valor l. – Potatoswatter

+0

Bueno, el resultado de ':: std :: vector :: operator []' está destinado a ser utilizado también como lvalue, y devuelve un carácter temporal como el de él. – Omnifarious

Cuestiones relacionadas