On Saturday, 2 March 2013 at 01:51:28 UTC, Steven Schveighoffer
wrote:
On Fri, 01 Mar 2013 20:37:26 -0500, Era Scarecrow
<[email protected]> wrote:
On Saturday, 2 March 2013 at 01:15:20 UTC, Steven
Schveighoffer wrote:
void main()
{
auto t = foo;
t++; // ok
foo++; // Error: foo() is not an lvalue
}
That should not be an error, or I should at least be able to
tell the compiler "this is NOT an rvalue, even if it seems
like one".
No, foo returns an lValue, however the ++ is likely wrong.
The compiler could have an ingrained belief that ++ is an
assignment operator meaning it requires an Lvalue, at which
point the code is wrong. But ++ is just an operator for the
struct, so I don't know.
You are saying opposite things "foo returns an LValue" "it
requires an Lvalue, at which point the code is wrong"
Sorry I hate typos. foo returns an Rvalue, therefore is an
Rvalue.
I contend that T is an LValue type. If the compiler can't see
that, it needs to be told, or it needs to get out of the way.
I just tested a simple "incx()" function that is identical to
the operator, and it works. I can even call the operator via
foo.opUnary!"++"() and it works! So the compiler is
restricting things that are trivially circumvented.
Anyways, because of how ++ and -- are assumed to basically also
be opAssign it requires an LValue, at least that's what the
compiler sees, and for simplicity it should probably continue to
follow that. Calling it explicitly removes the assumption it
requires an Lvalue. If it's const then calling it could be safe
as the object/temporary/Rvalue never changes. Hard to say.
Maybe it should be: calling a method of an rvalue, even if that
method is called via operator overload, should always be
allowed. Any simple field access should fail if the rvalue is
modified. So for instance foo.x++ should fail, but foo++
should work, even if all it does is x++. Maybe if the compiler
inlines the code and sees it trivially reduces to a rejected
case, it can reject it.