I'm writing an interface library that allows access to variables within tables (up to a theoretically infinite depth) in an object of type regula::State. I'm accomplishing this by overloading operator[] within a class, which then returns another of that same class, and calls operator[] again as needed. For example:

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

The above is supposed to place the value 3.14159 within variable pi in table math. Basically, it does this by have t return a proxy object representing math, which returns another proxy object representing pi, to which we actually save the variable. The internals of this aren't really relevant to the question, but here is the function header.

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

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

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

The T returned is just a copy of the value passed.

Now, my code produces NO errors in Visual C++ 2008 and works perfectly. But when I try to compile it on Linux with g++, I get the following error:

Post real code. Your samples are broken. regula::State t["math"]["pi"] = 3.14159; cannot be a valid C++ statement. The "fixed" declaration of your operator = is also broken, because now there's no T there
–
AnTDec 22 '09 at 17:42

@AndreyT: I apologize, that line was truncated when it shouldn't have been. I've fixed the sample in question.
–
pdusenDec 22 '09 at 17:50

1

Can you boil it down to a small snippet that demonstrates the error?
–
EclipseDec 22 '09 at 17:52

So, when you use the void return type on your operator =, it compiles and works in GCC?
–
AnTDec 22 '09 at 17:53

1

There's nothing obvious that stands out here. We'd need to see more of the implementation to help you. But based on experience and intuition, let me make a wild guess and say that you left out a typename disambiguator somewhere in your templated code. MSVC let's you get away with omitting it, while gcc often emits non-intuitive error messages.
–
Charles SalviaDec 22 '09 at 18:11

1 Answer
1

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.

Your operator= returns not only the wrong type, but not even an lvalue. Assuming GCC's error message didn't include any other candidates besides operator=(const regula::LObject&), GCC has simply ignored your overload entirely. The operator= it mentions is the default, automatically generated function.

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

Well it's true that the way operator = is declared is wrong, it's not necessarily true that operator [] is declared wrong. In point of fact, the specialization for ::std::vector<bool> defines operator [] to return a _Bit_reference (not a real reference). _Bit_reference in turn is a class the defines its own _Bit_reference &_Bit_reference::operator =(bool x).
–
OmnifariousDec 23 '09 at 7:13

His operator[] is valid; operator[] isn't required to return an lvalue at all far as I remember (not looking it up now). Point is, he's using it as an lvalue.
–
PotatoswatterDec 23 '09 at 8:28

Well, the result of ::std::vector<bool>::operator [] is intended to be used as an lvalue too, and it returns a temporary just like his does.
–
OmnifariousDec 23 '09 at 22:09

It's possible, but unlikely, that LObject is a proxy which passes modifications to another object. I'll stand by my advice.
–
PotatoswatterDec 24 '09 at 0:18

I ultimately solved my problem by a.) Having operator= be a void function, and b.) Manually casting to an appropriate type whenever the operators are used. Inconvenient, but since I'm basically writing this to scratch my own itch, I've decided I can deal with the compromise. Thanks for all of your input.
–
pdusenDec 24 '09 at 3:28