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

Reply via email to