Why does g ++ say that there is โ€œno match forโ€ operator = when explicitly there is, and Visual Studio can see what it is?

I am writing an interface library that allows access to variables in tables (up to theoretically infinite depth) in an object like regula::State . I accomplish this by overloading operator[] inside the class, which then returns another from the same class and calls operator[] again as needed. For example:

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

The above should put the value 3.14159 in the pi variable in the math table. Basically, he does this by using t returns a proxy object representing math , which returns another proxy object representing pi , to which we actually save the variable. The insides of this are not relevant to the question, but here is the function title.

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

Basically, in the above example, the program should call t operator[] with the string "math" and return another object, and then call this object operator[] with the string "pi" , which returns the final object, and then assigns a value to this using operator= .

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

The returned t is only a copy of the passed value .

Now my code does not cause errors in Visual C ++ 2008 and works fine. But when I try to compile it on Linux using g++ , I get the following 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&) 

For some reason, g++ trying to call operator= on operator[] , and not on the returned object, as expected.

I can fix this error by replacing the return type with operator= with void :

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

But this is not preferable, and in addition, I have similar errors in several other places with the same operator== overloaded:

 ../../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>())))))' 

I do not understand why this error occurs in g ++ or why it does not occur in Visual C ++. Can anyone shed some light on this or recommend any solutions?

+6
c ++ operators g ++ compiler-errors
source share
1 answer

Section 5.17 of the ISO standard states:

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

Your operator= returns not only the wrong type, but not even an lvalue. Assuming that the GCC error message does not contain any other candidates besides operator=(const regula::LObject&) , GCC simply completely ignored your overload. operator= , which he mentions, is an automatically created function by default.

At a second glance, your operator[] should also return a link. As written, no assignment expressions like your example should work at all.

So you should have functions

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

and

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

All Articles