www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - struct init property

reply nocide <benutzer example.com> writes:
struct has no default constructor and instances are initialized with the 
init property.
Can I declare or override the init property for a custom defined struct?
Aug 23 2012
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/23/2012 10:15 AM, nocide wrote:
 struct has no default constructor and instances are initialized with the
 init property.
 Can I declare or override the init property for a custom defined struct?

struct S { int i = 42; double d = 1.5; } void main() { assert(S.init == S(42, 1.5)); } That changes the .init value. You can also define a static opCall() to mimic the default constructor. Note that this method does not affect the .init value: struct S { int i; double d; static S opCall() { S s; s.i = 42; s.d = 1.5; return s; } } void main() { assert(S().i == 42); assert(S().d == 1.5); assert(S.init.i == int.init); import std.math; assert(isnan(S.init.d)); } Note that the static opCall() disables calling automatic destructor (i.e. the S(1, 2) does not work anymore). I am not sure whether that is one of the many struct-related issues at the moment. Ali
Aug 23 2012
parent nocide <benutzer example.com> writes:
[snip]

Ah thanks!

You just were a little bit faster :)
Aug 23 2012
prev sibling next sibling parent nocide <benutzer example.com> writes:
Am 23.08.2012 19:15, schrieb nocide:
 struct has no default constructor and instances are initialized with the
 init property.
 Can I declare or override the init property for a custom defined struct?

I've just realized, that I just have to declare default initializer for the members. This also works with unions! struct Foo { int a; union { int b = 7; float c; } }
Aug 23 2012
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, August 23, 2012 19:15:16 nocide wrote:
 struct has no default constructor and instances are initialized with the
 init property.
 Can I declare or override the init property for a custom defined struct?

The init property is defined by what you directly initialize the struct's member variables to. struct S { int i = 7; string s = "hello"; } S.init has a value of 7 for i and "hello" for s. Unfortunately, I don't believe that declaring an init function or property is currently disallowed, but if it affects S.init, it's a bug. - Jonathan M Davis
Aug 23 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 23-Aug-12 22:44, Namespace wrote:
 It would be great if you could declare your own .init as you can atm
 with "new" (http://dlang.org/class.html#allocators).

Note: Class allocators are deprecated in D2.
 For example:

 class Foo {
 public:
      init() {
          this = new typeof(this)();
      }
 }

 So you could avoid a null declaration by default. :)

-- Olshansky Dmitry
Aug 23 2012
next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 23-Aug-12 23:33, Namespace wrote:
 But to write your own init property would still be nice, or not?

Either way it has to be CTFEable. Can't you just do: struct A{ X field = generateX(); } and thus set .init to whatever you want. Otherwise it will inevitably rise question of the point of "= x;" syntax if initializes are overridden by custom .init. -- Olshansky Dmitry
Aug 23 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/23/2012 12:38 PM, Dmitry Olshansky wrote:
 On 23-Aug-12 23:33, Namespace wrote:
 But to write your own init property would still be nice, or not?

Either way it has to be CTFEable. Can't you just do: struct A{ X field = generateX(); } and thus set .init to whatever you want. Otherwise it will inevitably rise question of the point of "= x;" syntax if initializes are overridden by custom .init.

Yes, that works: struct S { int i = init_i(); double d = init_d(); static int init_i() { return 42; } static double init_d() { return 1.5; } } void main() { assert(S().i == 42); assert(S().d == 1.5); } So the language doesn't give us the ability to define a CTFE-able default constructor but writing individual "constructors" for each member works. Ali
Aug 23 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, August 23, 2012 21:33:57 Namespace wrote:
 But to write your own init property would still be nice, or not?

How would it be different from defining a default constructor? Structs specifically _don't_ have default constructors, because init must be known at compile time, and all kinds of restrictions would have to be placed on a default constructor (enough to make it pointless) to ensure that it would work as an init value that there's really no point to it. The kind of stuff that you'd want to do in a default constructor but can't do by directly initializing the member variables is precisely the kind of stuff that you _can't_ do with a struct, because init must be known at compile time, must always generate the same result, couldn't throw exceptions, etc. So, sure, at times it would be great to have a default constructor for structs, but other design decisions in the language (particularly with regards to init) simply make that infeasible. It's one of those "forced faults" in language design that Andrei likes to talk about. So, what we get is an init value defined by how the member variables are directly initialized and the ability to define a static opCall to get you the equivalent of the default constructor in cases where S() is used rather than S.init. It's not perfect, but there's not much that we can do about it. - Jonathan M Davis
Aug 23 2012
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 How would it be different from defining a default constructor? 
 Structs
 specifically _don't_ have default constructors, because init 
 must be known at
 compile time, and all kinds of restrictions would have to be 
 placed on a
 default constructor (enough to make it pointless) to ensure 
 that it would work
 as an init value that there's really no point to it. The kind 
 of stuff that
 you'd want to do in a default constructor but can't do by 
 directly
 initializing the member variables is precisely the kind of 
 stuff that you
 _can't_ do with a struct, because init must be known at compile 
 time, must
 always generate the same result, couldn't throw exceptions, etc.

 So, sure, at times it would be great to have a default 
 constructor for
 structs, but other design decisions in the language 
 (particularly with regards
 to init) simply make that infeasible. It's one of those "forced 
 faults" in
 language design that Andrei likes to talk about.

 So, what we get is an init value defined by how the member 
 variables are
 directly initialized and the ability to define a static opCall 
 to get you the
 equivalent of the default constructor in cases where S() is 
 used rather than
 S.init. It's not perfect, but there's not much that we can do 
 about it.

 - Jonathan M Davis

My idea was to declare your own .init in a class, not in a struct.
Aug 23 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
It would be great if you could declare your own .init as you can 
atm with "new" (http://dlang.org/class.html#allocators).

For example:

class Foo {
public:
     init() {
         this = new typeof(this)();
     }
}

So you could avoid a null declaration by default. :)
Aug 23 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
But to write your own init property would still be nice, or not?
Aug 23 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, August 23, 2012 23:27:18 Namespace wrote:
 My idea was to declare your own .init in a class, not in a struct.

Well, the init for classes will always be null, because class references are nullable. That's part of the language. Making it so that a class' init value wasn't guaranteed to be null would definitely complicate both the compiler and generic code (since it could no longer rely on the fact that a class' init value was null and would have to do additional checks when it cared). Right now, you have the guarantee that declaring a class reference allocates nothing, and changing init so that it could actually initialize the reference would break that guarantee. That would actually be a serious problem in cases where you need to be able to declare a class reference but can't initialize it when declaring it (e.g. a member variable, static variable, or global variable must be known at compile time if it's directly initialized, which can't be done with classes, since while you can sometimes use classes in CTFE, they can't be persisted beyond CTFE). If you want something that isn't nullable, you'll need a type which which isn't nullable, which means using a struct. I know that you want non-nullable references, but for D2, the best that you're going to get is a struct which wraps a class. - Jonathan M Davis
Aug 23 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 If you want something that isn't nullable, you'll need a type 
 which which
 isn't nullable, which means using a struct. I know that you 
 want non-nullable
 references, but for D2, the best that you're going to get is a 
 struct which
 wraps a class.

 - Jonathan M Davis

That would be fine if i only have to write: [code] void test(NotNullable!Foo f) { [/code] and not [code] Foo f = new Foo(); NotNullable!Foo nf = f; test(nf) [/code] as well. This overhead ist the same as if you use precondition. That's the reason why IMO NotNullable as struct isn't a good choice for that situation. But to overwrite the .init was just an idea, i didn't think that so much guarantees would be broken. Thanks for your explanation.
Aug 23 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, August 24, 2012 01:35:56 Namespace wrote:
 If you want something that isn't nullable, you'll need a type
 which which
 isn't nullable, which means using a struct. I know that you
 want non-nullable
 references, but for D2, the best that you're going to get is a
 struct which
 wraps a class.
 
 - Jonathan M Davis

That would be fine if i only have to write: [code] void test(NotNullable!Foo f) { [/code] and not [code] Foo f = new Foo(); NotNullable!Foo nf = f; test(nf) [/code] as well.

I would expect you to be able to do test(NotNullable!Foo(new Foo)); and with a helper function, you could have something like test(notNullable(new Foo)); - Jonathan M Davis
Aug 23 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 I would expect you to be able to do

 test(NotNullable!Foo(new Foo));

 and with a helper function, you could have something like

 test(notNullable(new Foo));

 - Jonathan M Davis

But then you have an lvalue and cannot receive it as "ref NotNullable!Foo". Your struct would be copied with the (default) postblit ctor every time you send it to "test", or am I wrong?
Aug 23 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, August 24, 2012 02:00:22 Namespace wrote:
 I would expect you to be able to do
 
 test(NotNullable!Foo(new Foo));
 
 and with a helper function, you could have something like
 
 test(notNullable(new Foo));
 
 - Jonathan M Davis

But then you have an lvalue and cannot receive it as "ref NotNullable!Foo". Your struct would be copied with the (default) postblit ctor every time you send it to "test", or am I wrong?

If you passed it a directly constructed NotNullable!Foo or the result of a function, then it wouldn't be copied. It would be moved. http://stackoverflow.com/questions/6884996/questions-about-postblit-and-move- semantics And even if it _were_ copied, we're talking about a struct that just holds a class reference, so copying it would be essentially the same as copying the reference. I wouldn't expect NotNullable to even _have_ a postblit constructor, meaning that copying it would use memcpy, which would be very fast. If you have to worry about the efficiency of passing NotNullable!T to a function, then there's something very wrong. - Jonathan M Davis
Aug 23 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
:D I didn't know that, thanks.
Aug 23 2012
prev sibling parent reply nocide <benutzer example.com> writes:
Am 23.08.2012 19:15, schrieb nocide:
 struct has no default constructor and instances are initialized with the
 init property.
 Can I declare or override the init property for a custom defined struct?

Ok, the initializer forks fine for me, but I've encounterd following situation: (simplified code) // This compile fine struct Foo { union { struct { int a = 1, b = 2, c = 3, d = 4; } float[4] e; } } // but this doesn't compile struct Foo { union { struct { int a, b, c, d; } float[4] e = [ 1.0f, 2.0f, 3.0f, 4.0f ]; } } Foo f; // Error: struct main.Foo overlapping initialization for struct Is this a bug?
Aug 24 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2012 09:39 AM, nocide wrote:
 Am 23.08.2012 19:15, schrieb nocide:
 struct has no default constructor and instances are initialized with the
 init property.
 Can I declare or override the init property for a custom defined struct?

Ok, the initializer forks fine for me, but I've encounterd following situation: (simplified code) // This compile fine struct Foo { union { struct { int a = 1, b = 2, c = 3, d = 4; } float[4] e; } } // but this doesn't compile struct Foo { union { struct { int a, b, c, d; } float[4] e = [ 1.0f, 2.0f, 3.0f, 4.0f ]; } } Foo f; // Error: struct main.Foo overlapping initialization for struct Is this a bug?

Yes.
Aug 24 2012