What if D would require * for reference types?

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Mon Jan 18 12:08:56 PST 2010


Steven Schveighoffer wrote:
> 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.

Isn't this already possible?

   class Foo { }

   Foo foo = new Foo;
   Foo* ptr = cast(Foo*) foo;

   // ptr is not a pointer to the reference.
   assert (ptr != &foo);


> 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.

I like it too. :) But I'm not sure we should use the & symbol:

   Foo& foo = new Foo;     // & denotes a reference
   Bar* bar = &barValue;   // & returns a pointer

Yes, C++ does it, but it's still ugly.

-Lars



More information about the Digitalmars-d mailing list