On Tue, 22 Dec 2009 11:05:52 -0500, Michel Fortin
<[email protected]> wrote:
On 2009-12-22 08:45:00 -0500, "Steven Schveighoffer"
<[email protected]> said:
The point is, wrapper types shouldn't have second-class citizenship as
rvalues to pointers and references. There's got to be a way to
identify types as being lvalues even though the compiler doesn't see
it that way. If you can accomplish that, then I have no problem
disallowing setting members of true rvalues.
What you need is tail const. Lvalues are similar to tail-const values:
can't change them, but can change what they point to. The lvalueness is
not transitive, so a transitive const isn't appropriate for representing
lvalues.
Then of course you need to annotate member functions as being
tail-const, and there the const system becomes more complicated.
You mean head-const. We have tail-const already (I often get them
confused too).
But that's not exactly what I mean. Constancy aside, if I have a wrapper
struct like this:
class C
{
void setX(int n){...}
@property S s() {return S(this);}
}
struct S
{
private C c;
@property void x(int n) { c.setX(n); }
}
I should be able to do this:
auto c = new C;
c.s.x = 5;
Basically, s is giving a restrictive interface to a C, using the power of
struct member functions, I can filter what functions are available or what
they are named, or log them, or do whatever I want. It's a wrapper type.
If s's functions are inlined, then S has almost no overhead, it just
provides static interface transformation.
Even if there was an annotation like:
@lvalue struct S
{
}
which hints to the compiler that S can be used as an lvalue, I'd be more
than happy to accept Andrei's proposed restriction.
-Steve