July 11, 2012
On Wednesday, 11 July 2012 at 06:48:59 UTC, David Nadlinger wrote:
> On Wednesday, 11 July 2012 at 06:34:29 UTC, Tobias Pankrath wrote:
>>> This escapes a stack reference.
>>
>> Ins't b supposed to be allocated on the heap?
>
> The Bar instance is, but the pointer to it is not. Making _b a Rebindable instead of using a pointer (to what effectively is a pointer to the real object) should help.
>
> David

Bar b = new Bar;
auto b2 = &b; // type of b2 is Bar*

So does it meen, that a pointer of type Bar* does not point to the real object?
How do I get such a pointer then and which type does it have?

July 11, 2012
On Wednesday, July 11, 2012 09:00:26 Tobias Pankrath wrote:
> Bar b = new Bar;
> auto b2 = &b; // type of b2 is Bar*
> 
> So does it meen, that a pointer of type Bar* does not point to the real object?

It's a pointer to a reference, not to the object.

> How do I get such a pointer then and which type does it have?

I don't think that you can. It's a reference, not a pointer. And if you _can_ do it, I bet that it's not at all pretty. References are _not_ intended to be treated the same as pointers. They're similar, but they're fundamentally different. And instances of classes are intended to be referred to by references, _not_ be pointed to by pointers.

Rebindable is the correct solution to this "readonly" issue.

- Jonathan M Davis
July 11, 2012
On 07/11/12 09:00, Tobias Pankrath wrote:
> On Wednesday, 11 July 2012 at 06:48:59 UTC, David Nadlinger wrote:
>> On Wednesday, 11 July 2012 at 06:34:29 UTC, Tobias Pankrath wrote:
>>>> This escapes a stack reference.
>>>
>>> Ins't b supposed to be allocated on the heap?
>>
>> The Bar instance is, but the pointer to it is not. Making _b a Rebindable instead of using a pointer (to what effectively is a pointer to the real object) should help.
>>
>> David
> 
> Bar b = new Bar;
> auto b2 = &b; // type of b2 is Bar*
> 
> So does it meen, that a pointer of type Bar* does not point to the real object?

Yeah, unfortunately.
Can anybody think of a reason to keep the current (broken) behavior?

> How do I get such a pointer then and which type does it have?

You can use something like this:

   static struct ClassPtr(C) if (is(C==class)) {
      // '__cp' is not the same as what the compiler currently considers a class
      // pointer; it is used here as a container for the reference. This adds the
      // missing level of indirection, which allows for the necessary different
      // (but still compatible) types.
      private C* __cp;

      pure: @safe: nothrow:
      @trusted this(C o) { __cp = cast(C*)o; }
      @trusted C opAssign(C o) { __cp = cast(C*)o; return o; }

      @trusted @property C get() { return cast(C)__cp; }
      @trusted @property const(C) get() const { return cast(C)__cp; }
      alias get this;
   }

   // Eg:
   class Bar {}
   class Foo { ClassPtr!(const Bar) _b; void SetBar(const Bar b) { _b = b; } }


And - no - this shouldn't be necessary.

artur
July 11, 2012
On Wednesday, 11 July 2012 at 08:56:39 UTC, Artur Skawina wrote:
> On 07/11/12 09:00, Tobias Pankrath wrote:
>> Bar b = new Bar;
>> auto b2 = &b; // type of b2 is Bar*
>> 
>> So does it meen, that a pointer of type Bar* does not point to the real object?
>
> Yeah, unfortunately.
> Can anybody think of a reason to keep the current (broken) behavior?

Why would it be broken? Bar intrinsically is a reference type, so Bar* is a pointer to a reference.

David
July 11, 2012
On Wednesday, 11 July 2012 at 09:49:43 UTC, David Nadlinger wrote:
> On Wednesday, 11 July 2012 at 08:56:39 UTC, Artur Skawina wrote:
>> On 07/11/12 09:00, Tobias Pankrath wrote:
>>> Bar b = new Bar;
>>> auto b2 = &b; // type of b2 is Bar*
>>> 
>>> So does it meen, that a pointer of type Bar* does not point to the real object?
>>
>> Yeah, unfortunately.
>> Can anybody think of a reason to keep the current (broken) behavior?
>
> Why would it be broken? Bar intrinsically is a reference type, so Bar* is a pointer to a reference.
>
> David

The languages conflates reference and instance type for classes. See here http://dpaste.dzfl.pl/a55ad2b6 . I wouldn't say this should change but it is a minor inconsistency I just stumbled on.


July 11, 2012
On 07/11/12 11:49, David Nadlinger wrote:
> On Wednesday, 11 July 2012 at 08:56:39 UTC, Artur Skawina wrote:
>> On 07/11/12 09:00, Tobias Pankrath wrote:
>>> Bar b = new Bar;
>>> auto b2 = &b; // type of b2 is Bar*
>>>
>>> So does it meen, that a pointer of type Bar* does not point to the real object?
>>
>> Yeah, unfortunately.
>> Can anybody think of a reason to keep the current (broken) behavior?
> 
> Why would it be broken? Bar intrinsically is a reference type, so Bar* is a pointer to a reference.

Because it doesn't let you have a real pointer to a class.

The obvious alternative would be:

   auto r = new Bar(); // reference
   Bar* p = r;         // pointer to Bar; ref implicitly converts to pointer.
   auto pr = &r;       // typeof(pr)==Bar** ; can't do better w/o ref types.

So, does the current scheme have any advantages?
(currently, the second example is illegal and the last '&r' expression results
 in 'Bar *')

artur
July 11, 2012
On Wednesday, 11 July 2012 at 10:00:33 UTC, Tobias Pankrath wrote:
> The languages conflates reference and instance type for classes. See here http://dpaste.dzfl.pl/a55ad2b6 . I wouldn't say this should change but it is a minor inconsistency I just stumbled on.

This is not an inconsistency, but by design. Classes intrinsically are reference types, there isn't something like an »instance type« for them, which helps avoiding things like the slicing problem in C++. Yes, in D, types are always only either value types (structs) or polymorphic reference types (classes), but I fail to see anything inconsistent here.

David
July 11, 2012
On Wednesday, 11 July 2012 at 10:05:40 UTC, Artur Skawina wrote:
> Because it doesn't let you have a real pointer to a class.

What is a »real pointer«? Class references are really just pointers, in a way – you can cast them to void*.

> The obvious alternative would be:
>
>    auto r = new Bar(); // reference
>    Bar* p = r;         // pointer to Bar; ref implicitly converts to pointer.
>    auto pr = &r;       // typeof(pr)==Bar** ; can't do better w/o ref types.
>
> So, does the current scheme have any advantages?

When discussing a language change, the question should always be: Does the _new_ scheme have any advantages?

David
July 11, 2012
On 07/11/2012 08:52 AM, David Nadlinger wrote:

> I fail to see anything inconsistent here.

Most other operations act on the object:

class B
{
    // ...
}

auto b = new B();

++b;    // on the object
b > b;  // on the object
// etc.
&b;     // on the reference

That can be seen as an inconsistency. Perhaps it is that the non-overridable operators are on the class reference?

Ali

July 11, 2012
On 07/11/12 17:54, David Nadlinger wrote:
> On Wednesday, 11 July 2012 at 10:05:40 UTC, Artur Skawina wrote:
>> Because it doesn't let you have a real pointer to a class.
> 
> What is a »real pointer«? Class references are really just pointers, in a way – you can cast them to void*.

A "real pointer" is a pointer.
Class refs are basically pointers, but with some extra limitations and syntax
sugar. The key distinction is that you can implement references on top of
pointers, but the opposite isn't true. Hence refs are not "real" pointers.
Casting refs in order to extract their value /is/ possible, but that gets
ugly and dangerous (if not actually 'undefined'); the ClassPtr type that
i posted in this thread is a good example - it may be just ~6 lines of code,
but that's six line of code that everybody that's reading or using it must
analyze, before determining if it's correct and sane. (and, yes, it's not
perfect, eg it doesn't even try to handle immutable - simply because I had
no need for that so far)

>> The obvious alternative would be:
>>
>>    auto r = new Bar(); // reference
>>    Bar* p = r;         // pointer to Bar; ref implicitly converts to pointer.
>>    auto pr = &r;       // typeof(pr)==Bar** ; can't do better w/o ref types.
>>
>> So, does the current scheme have any advantages?
> 
> When discussing a language change, the question should always be: Does the _new_ scheme have any advantages?

Yeah, except when the old scheme was an accident, which I have to assume is the case here. Hence the questions, just in case the behavior was in fact chosen deliberately and I'm missing something.

The advantages of having pointers to classes? Eg solving the problem that
triggered this thread w/o hacks like ClassPtr (Rebindable is an even worse
hack). [1]
Not to mention that the current model is extremely misleading; consider that
three different people got it wrong in this thread alone...

artur

[1] "direct" pointers, going via a ref obviously works, even if less efficient. Which brings us back to the question - are there any advantages of /that/ scheme?