www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - inout constructor?

reply bearophile <bearophileHUGS lycos.com> writes:
In this bug report I've seen an inout struct constructor:
http://d.puremagic.com/issues/show_bug.cgi?id=7369


struct TestStruct {
    this(int data) inout {}
}

Do you know what's the usage of this?

Bye and thank you,
bearophile
Jan 25 2012
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 25 Jan 2012 23:08:01 -0500, bearophile <bearophileHUGS lycos.com>  
wrote:

 In this bug report I've seen an inout struct constructor:
 http://d.puremagic.com/issues/show_bug.cgi?id=7369


 struct TestStruct {
     this(int data) inout {}
 }

 Do you know what's the usage of this?

I would say possibly something like this: struct TestStruct { int *data; this(inout(int)* d) inout { this.data = d; } // allowed just like a const ctor can set its members once. } int xm; const(int) xc; immutable(int) xi; auto tsm = TestStruct(&xm); auto tsc = TestStruct(&xc); auto tsi = TestStruct(&xi); writeln(typeof(tsm).stringof); // TestStruct writeln(typeof(tsc).stringof); // const(TestStruct) writeln(typeof(tsi).stringof); // immutable(TestStruct) I'll note that I don't think this is currently supported, but I could see how it would be useful. However, in that bug report, there are no inout parameters besides the 'this' pointer, so I'm not sure what the purpose would be there. -Steve
Jan 26 2012
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 26/01/2012 15:27, Steven Schveighoffer wrote:
<snip>
 auto tsm = TestStruct(&xm);
 auto tsc = TestStruct(&xc);
 auto tsi = TestStruct(&xi);

 writeln(typeof(tsm).stringof); // TestStruct
 writeln(typeof(tsc).stringof); // const(TestStruct)
 writeln(typeof(tsi).stringof); // immutable(TestStruct)

To actually get an immutable object (trying it on DMD 2.057), you need to use auto tsi = immutable(TestStruct)(&xi); I think the reason is: Think of a constructor as a method that always returns this. The implicit this pointer points to a space that has been allocated in advance to hold the constructed object. this(inout(int)* d) inout { this.data = d; } auto ts = TestStruct(&xi); is essentially inout(TestStruct) ctor(inout(int)* d) inout { this.data = d; return this; } TestStruct temp; auto ts = temp.ctor(&xi); The implicit this pointer is a TestStruct* (mutable), but &xi is an immutable(int*). The only way to match both is to match the inout as const, so a const is what it returns. But it doesn't work properly with a class instead of a struct at the moment.
 I'll note that I don't think this is currently supported, but I could see how
it would be
 useful.

You away from your usual testing station?
 However, in that bug report, there are no inout parameters besides the 'this'
pointer, so
 I'm not sure what the purpose would be there.

The purpose of it in the example is to be a minimal testcase for the bug. But in the general case, the purpose is to enable a mutable, const or immutable object to be constructed to wrap existing data that has the same constancy. Stewart.
Jan 27 2012
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 27 Jan 2012 08:05:24 -0500, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 On 26/01/2012 15:27, Steven Schveighoffer wrote:
 <snip>
 auto tsm = TestStruct(&xm);
 auto tsc = TestStruct(&xc);
 auto tsi = TestStruct(&xi);

 writeln(typeof(tsm).stringof); // TestStruct
 writeln(typeof(tsc).stringof); // const(TestStruct)
 writeln(typeof(tsi).stringof); // immutable(TestStruct)

To actually get an immutable object (trying it on DMD 2.057), you need to use auto tsi = immutable(TestStruct)(&xi);

Right, the above is a proposed behavior for inout constructors. The point is that an inout constructor could be useful for replacing three constructors, each of which would have to be marked const, immutable, or mutable (no marks).
 I think the reason is: Think of a constructor as a method that always  
 returns this.  The implicit this pointer points to a space that has been  
 allocated in advance to hold the constructed object.

      this(inout(int)* d) inout {
          this.data = d;
      }

      auto ts = TestStruct(&xi);

 is essentially

      inout(TestStruct) ctor(inout(int)* d) inout {
          this.data = d;
          return this;
      }

      TestStruct temp;
      auto ts = temp.ctor(&xi);

This is not true. A constructor used on an initializer is special in that the constructed struct does not logically exist before the construction. This may be the way it currently works in the compiler, but that is a bug. Essentially, this: this(inout(int)* d) inout { this.data = d; } should reduce to this: this( int * d) {this.data = d;} this( const(int)* d) const {this.data = d;} this(immutable(int)* d) immutable {this.data = d;} Which already works today (the three constructors I mean).
 The implicit this pointer is a TestStruct* (mutable), but &xi is an  
 immutable(int*).  The only way to match both is to match the inout as  
 const, so a const is what it returns.

No, the implicit this pointer's constancy is decided by the attribute on the constructor. In the case of constructors, the const or immutable attribute becomes the attribute of the return value. Inside the constructor, special rules are used. For example, you can assign to member variables once, even in a const or immutable ctor.
 But it doesn't work properly with a class instead of a struct at the  
 moment.

I just tested, and it actually compiles for a struct, but doesn't work properly. Instead I get const for both immutable and const.
 I'll note that I don't think this is currently supported, but I could  
 see how it would be
 useful.

You away from your usual testing station?

No, just busy (and a little lazy) :) I tested it now, and I see it doesn't do the proper thing.
 However, in that bug report, there are no inout parameters besides the  
 'this' pointer, so
 I'm not sure what the purpose would be there.

The purpose of it in the example is to be a minimal testcase for the bug. But in the general case, the purpose is to enable a mutable, const or immutable object to be constructed to wrap existing data that has the same constancy.

Yes, I agree. But you need to put inout on the parameter in order for it to properly reach the result (the constructed object) I suspect the special case of the ctor is not treated correctly. I'll file a bug. -Steve
Jan 27 2012