What if D would require * for reference types?

Steven Schveighoffer schveiguy at yahoo.com
Mon Jan 18 11:48:50 PST 2010


On Mon, 18 Jan 2010 13:35:01 -0500, Bill Baxter <wbaxter at gmail.com> wrote:

> I think one can argue it would be better for pointer arithmetic to
> require a more in-your-face notation, since pointer arithmetic isn't
> usually needed and won't even be allowed in SafeD.
>
> It isn't really standard arithmetic to begin with, since foo++
> (pointer meaning) is more like  foo += sizeof(Foo);
> Also adding pointers together is not allowed.  These two things, I
> think, form the basis of a decent justification for making pointer
> arithmetic syntactically distinct from regular arithmetic.
>
> So, for instance, you could require distinct operators like  *++, *+,
> *-  for pointer manipulations.
>
> Maybe we're on to another big mistake of C here -- conflation of
> pointers with numbers.  Or at least a corollary to the mistake of
> conflating of arrays with pointers.
>
> The question that then comes up is can you do overloading of those new
> operators?  If you want to make something that is "pointer-like", then
> it would be necessary to do so.  But probably  only value-types should
> be allowed to act in a pointer-like manner.  So you could only
> overload pointer arithmetic operators in a struct.  But I'm not sure
> there's a use case for even that.
>

pointers are essentially unrestricted arrays also.  So you'd also have to  
disallow ptr[x].  Basically any operation that normally gets forwarded to  
a class reference but would be intercepted by the pointer has to be given  
a new syntax.

I'm wondering, is there an issue with signifying rebindable references  
like C++'s references, i.e. C&  ? (question mark separated for clarity)

C& classref = new C();
C& classref2 = classref; // does not create a new instance, but just  
copies the reference
S& structref = new S(); // struct reference!
S& structref2 = structref; // structref2 and structref bind to same data.
S structref3 = *structref2; // must dereference to access value
*classref2 = *classref; // Error! illegal to derference class references.
S& structref4 = &structref3; // pointer implicitly casts to reference.
C classref3; // illegal
const(C)& constref; // tail-const class reference!

ref can still be used as a storage class, meaning you can use it as if it  
were a value type.  But the & types will be explicitly a reference type,  
meaning:

foo(ref int x; int& y)
{
    int z;
    assert(is(typeof(z) == typeof(x));
    assert(is(typeof(y) != typeof(x) && typeof(y) != typeof(z));

    y = z; // illegal;
    *y = z; // correct;
    y = &z; // correct, but unsafe.
    y = x; // also illegal
    y = &x; // ok (possibly unsafe).

    y += 5; // compiler error or equivalent to *y += 5 ?
}

basically, & is a pointer that only supports the operators = * and 'is'.   
I think conversion from a reference to a pointer should be available via a  
cast, but I'm not sure whether the compiler should allow class pointers.   
My gut feeling is no.

Are there any syntax ambiguities here?  & is also a binary op, but then  
again, so is *.  Will there be an issue with && ? I mean, because the  
references are rebindable, you should be able to have a reference to a  
reference.

Also, struct references in this way will be usable in safe D, enabling  
heap struct data!

The more I think about it, the more I like having an explicit reference  
denotation for classes, with the compiler enforcing that you simply can't  
use class data as a value type.  This basically makes all the tail-X  
syntax just work, and still retains the benefits of classes being  
reference-only types.  The tail shared problem is a really crappy issue,  
worse than tail-const.

-Steve



More information about the Digitalmars-d mailing list