www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - struct constructor co nfusion

reply Spacen Jasset <spacen razemail.com> writes:
Hello,

I have read various things about struct constructors, 
specifically 0 argument constructors, and using opCall and 
 disable this(); which no longer seems to work.

What I am after I think is the behavior of C++'s structs on the 
stack, namely for some or all of these uses at a given time:


1. Allocation on the stack
2. Value type semantics
3. RAII (combined with (1) often)

The scope keyword on classes has been deprecated, it seems 
because it was hard to detect returning destroyed scope 
references, otherwise that might have done the job.


Is it the case that a struct should now be used with a factory 
method? Does this also mean that the struct destructor must be 
made to work when .init is called instead of the factory method?

This idiom is inconsistent with struct constructors that do have 
one or more arguments, and I think that this question is likely 
to arise time immemorial from others who are not expecting this 
particular inconstancy.

Would it not make sense to ban constructors on structs entirely 
-- or find another solution that clears this up?
Nov 06 2015
parent reply Atila Neves <atila.neves gmail.com> writes:
On Friday, 6 November 2015 at 17:34:29 UTC, Spacen Jasset wrote:
 Hello,

 I have read various things about struct constructors, 
 specifically 0 argument constructors, and using opCall and 
  disable this(); which no longer seems to work.

 What I am after I think is the behavior of C++'s structs on the 
 stack, namely for some or all of these uses at a given time:


 1. Allocation on the stack
 2. Value type semantics
 3. RAII (combined with (1) often)
This is common in D as well. The difference to C++ is 0-argument struct constructors to do extra work to satisfy invariants.
 Is it the case that a struct should now be used with a factory 
 method? Does this also mean that the struct destructor must be
It's the easiest way to emulate C++'s 0-argument struct constructors.
 made to work when .init is called instead of the factory method?
If the factory method isn't called, then yes, the destructor shouldn't blow up just because all the struct members are T.init.
 This idiom is inconsistent with struct constructors that do 
 have one or more arguments, and I think that this question is 
 likely to arise time immemorial from others who are not 
 expecting this particular inconstancy.
How is it inconsistent? Nobody stops me from doing this: struct Struct { void* ptr = cast(void*)5; this(int size) { ptr = malloc(size); } ~this() { free(ptr); } } void main() { auto ok = Struct(10); //auto oops = Struct.init; } Atila
Nov 06 2015
parent reply Spacen Jasset <spacen razemail.com> writes:
On Friday, 6 November 2015 at 17:50:17 UTC, Atila Neves wrote:
 On Friday, 6 November 2015 at 17:34:29 UTC, Spacen Jasset wrote:
 Hello,

 I have read various things about struct constructors, 
 specifically 0 argument constructors, and using opCall and 
  disable this(); which no longer seems to work.

 What I am after I think is the behavior of C++'s structs on 
 the stack, namely for some or all of these uses at a given 
 time:


 1. Allocation on the stack
 2. Value type semantics
 3. RAII (combined with (1) often)
This is common in D as well. The difference to C++ is 0-argument struct constructors to do extra work to satisfy invariants.
 Is it the case that a struct should now be used with a factory 
 method? Does this also mean that the struct destructor must be
It's the easiest way to emulate C++'s 0-argument struct constructors.
 made to work when .init is called instead of the factory 
 method?
If the factory method isn't called, then yes, the destructor shouldn't blow up just because all the struct members are T.init.
 This idiom is inconsistent with struct constructors that do 
 have one or more arguments, and I think that this question is 
 likely to arise time immemorial from others who are not 
 expecting this particular inconstancy.
How is it inconsistent? Nobody stops me from doing this: struct Struct { void* ptr = cast(void*)5; this(int size) { ptr = malloc(size); } ~this() { free(ptr); } } void main() { auto ok = Struct(10); //auto oops = Struct.init; } Atila
What I mean is that: this(int a, int b) {} is allowed Whereas: this() {} isn't allowed. I see why that is the case now, but it seems inconsistent to me, and I think each new person that comes to D is going to wonder about this. Also, I had to add a dummy private constructor to make my structs 'createable', or is there another way? e.g. struct Texture { disable this(); static Texture create() { return Texture(0); } ... private: this(int) { glGenTextures(1, &textureId_); enforce(0 != textureId_); } GLuint textureId_; }
Nov 06 2015
parent anonymous <anonymous example.com> writes:
On 06.11.2015 20:05, Spacen Jasset wrote:
 Also, I had to add a dummy private constructor to make my structs
 'createable', or is there another way?

 e.g.

 struct Texture
 {
       disable this();
      static Texture create()
      {
      return Texture(0);
      }

 ...

 private:
      this(int)
      {
          glGenTextures(1, &textureId_);
          enforce(0 != textureId_);
      }

      GLuint textureId_;
 }
You can use Texture.init to initialize a variable: ---- struct Texture { disable this(); static Texture create() { Texture t = Texture.init; glGenTextures(1, &t.textureId_); enforce(0 != t.textureId_); return t; } private: GLuint textureId_; } ----
Nov 06 2015