Why can't we define re-assignable const reference variable?

Steven Schveighoffer schveiguy at yahoo.com
Tue Feb 19 07:57:34 PST 2008


"none" wrote
> Why can't we define re-assignable const reference variable?
> i.e. the variable can be re-bind, but it's allowed to change the object it
> points to:

The problem here, none (is that your real name?), is that Walter has tried 
several times to achieve exactly that, and each time the syntax that he has 
created is either confusing or breaks something else.  I think he has given 
up, claiming that there is no way to do it, but I think he is wrong in that 
respect.

The problem stems from the fact that classes are inherently references and 
everything else is not.  This in itself is not a problem, and is a 
distinction I happen to agree with, but the issue is that there is no easy 
way to const-modify the data of a class without also modifying the reference 
to the data.  In order for this to work, there needs to be a syntax change.

In all the responses to this thread, there is one point of view that I wish 
to rebut:

"You can't have mutable references to const classes because any syntax 
change you have to make would break generic programming"

Generic programming is already broken.  That is, because classes *are* 
references and must be created from the heap using the new operator, you 
must treat them differently today than other types.  For example, if I want 
to create a generic type that creates a new version of a type, or uses an 
array of the type, depending on whether the type is a class or a struct or 
something else, I need to use static if to determine this before creating 
the new type.

I believe others have pointed out other examples, but it all comes down to 
the fact that yes, classes are inherently different than structs or other 
data types, and you have to treat them differently, so saying you cannot 
change the language because then you'd have to treat classes differently 
than other types is asinine.

I have proposed two syntax changes that I believe would resolve the problem. 
One is to allow dereferencing a class type, such as:

const(*C)* c;

Which would translate to *C being the value of type C, and therefore 
const(*C)* being exactly what we want.  This does not add any keywords, and 
also utilizes the * operator in familiar ways, and so it would be in my mind 
trivial to introduce and implement in the compiler.  The only issue is that 
you must restrict the user from declaring a variable or return type of the 
dereferenced class type.  i.e.:

*C cvalue;

would be illegal.

The only drawback here is that code is going to get really ugly, but I can 
live with this because we can make templates that make the code look better. 
And in fact, this *fixes* to some degree the difference between classes and 
structs for generic programming, because if you want a reference type, you 
can do:

valuetype(T)
{
   static if(is(T == class))
      alias *T valuetype;
   else
      alias T valuetype;
}

struct hasTailconstRef(T)
{
    const(valuetype!(T)) * myref;
}

now, hasTailconstRef.myref is a tailconst reference to a type no matter if 
the type is a class, struct, int, or whatever.

The other proposal I have made, which I like better but would be a more 
drastic syntax change, is to have a reference operator that "pulls out" the 
reference on a class.  Other types would be treated like references to the 
type:

struct S {}
class C {}

S & s; // equivalent to S * s
C & c; // equivalent to C c
int & i; // equivalent to int * i

With this, you can then use the & operator to declare a tailconst reference 
to a class or struct equivalently:

const(C) & c;
const(S) & s;

I have never read any arguments that correctly refute that these options 
would work.  All I have ever heard is the generic programming argument, 
which is totally bogus, and "we've already tried tail-const, it doesn't 
work", which isn't an argument at all.

I challenge anyone to tell me why either of these schemes would not work.

-Steve 





More information about the Digitalmars-d mailing list