www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Whats going on with this?

reply claptrap <clap trap.com> writes:
---
import std;

import std.stdio;

struct Foo
{
     int a = 0, b = 0;

     this(int[2] vars)
     {
         this.a = vars[0];
         this.b = vars[1];
     //    writeln("constructor called");
     }

}

Foo foo = [300,300];

void main()
{
     writeln(foo.a);
}
---

Compiles and works OK. I cant see anything in the struct docs 
explaining why that array on the right hand side is automatically 
converted to a constructor call.

Weird thing is if you un-comment the writeln in the constructor 
it wont compile. You get this...

/dlang/dmd/linux/bin64/../../src/phobos/std/stdio.d(4839): Error: 
variable impl cannot be modified at compile time
/dlang/dmd/linux/bin64/../../src/phobos/std/stdio.d(3806):        
called from here: makeGlobal()
/dlang/dmd/linux/bin64/../../src/phobos/std/stdio.d(3896):        
called from here: trustedStdout()
onlineapp.d(13):        called from here: writeln("constructor 
called")
onlineapp.d(18):        called from here: Foo(0, 0).this([300, 
300])

How ever if you move Point foo declaration into the main function 
it works OK.

What exactly is going on? I mean it looks like the Foo is default 
constructed and then constructed on top with a call to the arary 
constructor? But why?

Why would putting in the writeln cause it to fail? Is it maybe 
trying to create the foo at compile time?
Oct 02 2020
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/2/20 7:28 PM, claptrap wrote:

 Why would putting in the writeln cause it to fail? Is it maybe trying to 
 create the foo at compile time?
 
Yes, it is. Any static initialization of static variables happens at compile-time. https://dlang.org/spec/declaration.html#global_static_init -Steve
Oct 02 2020
parent reply claptrap <clap trap.com> writes:
On Saturday, 3 October 2020 at 00:15:02 UTC, Steven Schveighoffer 
wrote:
 On 10/2/20 7:28 PM, claptrap wrote:

 Why would putting in the writeln cause it to fail? Is it maybe 
 trying to create the foo at compile time?
 
Yes, it is. Any static initialization of static variables happens at compile-time. https://dlang.org/spec/declaration.html#global_static_init -Steve
Ah.. ok, any idea why this works? Foo foo = [300,300]; Tbh I though I'd defined opAssign to take an array, and was just seeing if it worked, but I hadn't and it seems it's calling the constructor that takes an array, but I cant see in the docs why the above code gets converted to a constructor call.
Oct 03 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/3/20 6:52 AM, claptrap wrote:
 On Saturday, 3 October 2020 at 00:15:02 UTC, Steven Schveighoffer wrote:
 On 10/2/20 7:28 PM, claptrap wrote:

 Why would putting in the writeln cause it to fail? Is it maybe trying 
 to create the foo at compile time?
Yes, it is. Any static initialization of static variables happens at compile-time. https://dlang.org/spec/declaration.html#global_static_init
Ah.. ok, any idea why this works? Foo foo = [300,300];
Yeah, it's calling the constructor. I agree with Adam, there's nothing in the spec that talks about this that I can find. -Steve
Oct 03 2020
next sibling parent Daniel Kozak <kozzi11 gmail.com> writes:
On Sat, Oct 3, 2020 at 4:45 PM Steven Schveighoffer via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 On 10/3/20 6:52 AM, claptrap wrote:
 On Saturday, 3 October 2020 at 00:15:02 UTC, Steven Schveighoffer wrote:
 On 10/2/20 7:28 PM, claptrap wrote:

 Why would putting in the writeln cause it to fail? Is it maybe trying
 to create the foo at compile time?
Yes, it is. Any static initialization of static variables happens at compile-time. https://dlang.org/spec/declaration.html#global_static_init
Ah.. ok, any idea why this works? Foo foo = [300,300];
Yeah, it's calling the constructor. I agree with Adam, there's nothing in the spec that talks about this that I can find. -Steve
I would say it is here you just need to read it carefully: https://dlang.org/spec/struct.html#static_struct_init
Oct 03 2020
prev sibling parent reply Daniel Kozak <kozzi11 gmail.com> writes:
On Sat, Oct 3, 2020 at 10:40 PM Daniel Kozak <kozzi11 gmail.com> wrote:

 I would say it is here you just need to read it carefully:

 https://dlang.org/spec/struct.html#static_struct_init
For case specification is change I will paste it here: ''' If a StructInitializer is supplied, the fields are initialized by the StructMemberInitializer syntax. StructMemberInitializers with the Identifier : NonVoidInitializer syntax may be appear in any order, where Identifier is the field identifier. StructMemberInitializers with the NonVoidInitializer syntax appear in the lexical order of the fields in the StructDeclaration. ''' And StructMemberInitializer is defined as: ''' StructMemberInitializer: NonVoidInitializer Identifier : NonVoidInitializer ''' And NonVoidInitializer is defined as: ''' NonVoidInitializer: ExpInitializer ArrayInitializer StructInitializer ''' And as you can see there is ArrayInitializer And there is definition of Array literals here https://dlang.org/spec/expression.html#array_literals and in section 2. there is this text: ''' By default, an array literal is typed as a dynamic array, but the element count is known at compile time. So all array literals can be implicitly converted to static array types. '''
Oct 03 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/3/20 4:46 PM, Daniel Kozak wrote:
 
 
 On Sat, Oct 3, 2020 at 10:40 PM Daniel Kozak <kozzi11 gmail.com 
 <mailto:kozzi11 gmail.com>> wrote:
 
     I would say it is here you just need to read it carefully:
 
     https://dlang.org/spec/struct.html#static_struct_init
 
 
 For case specification is change I will paste it here:
 '''
 If a StructInitializer is supplied, the fields are initialized by the 
 StructMemberInitializer syntax. StructMemberInitializers with the 
 Identifier : NonVoidInitializer syntax may be appear in any order, where 
 Identifier is the field identifier. StructMemberInitializers with the 
 NonVoidInitializer syntax appear in the lexical order of the fields in 
 the StructDeclaration.
 '''
 
 And StructMemberInitializer is defined as:
 
 '''
 StructMemberInitializer:
      NonVoidInitializer
      Identifier : NonVoidInitializer
 '''
 
 And NonVoidInitializer is defined as:
 
 '''
 NonVoidInitializer:
      ExpInitializer
      ArrayInitializer
      StructInitializer
 '''
 
 And as you can see there is ArrayInitializer
 
 And there is definition of Array literals here
 https://dlang.org/spec/expression.html#array_literals
 
 and in section 2. there is this text:
 
 '''
 By default, an array literal is typed as a dynamic array, but the 
 element count is known at compile time. So all array literals can be 
 implicitly converted to static array types.
 '''
"StructMemberInitializers with the NonVoidInitializer syntax appear in the lexical order of the fields in the StructDeclaration" seems to suggest it will not call the constructor, but instead initialize the fields according to the list. The fields are not a static array, so clearly it is calling the constructor, and not initializing the fields. I really don't think this case is in the spec. But I know it works, for instance: Variant v = anything; If this required an explicit Variant constructor, it would be quite annoying. -Steve
Oct 03 2020
parent Daniel Kozak <kozzi11 gmail.com> writes:
On Sat, Oct 3, 2020 at 11:30 PM Steven Schveighoffer via
Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 "StructMemberInitializers with the NonVoidInitializer syntax appear in
 the lexical order of the fields in the StructDeclaration" seems to
 suggest it will not call the constructor, but instead initialize the
 fields according to the list.

 The fields are not a static array, so clearly it is calling the
 constructor, and not initializing the fields.

 I really don't think this case is in the spec.

 But I know it works, for instance:

 Variant v = anything;

 If this required an explicit Variant constructor, it would be quite
 annoying.

 -Steve
Yes you are right
Oct 03 2020
prev sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 2 October 2020 at 23:28:04 UTC, claptrap wrote:
 I cant see anything in the struct docs explaining why that 
 array on the right hand side is automatically converted to a 
 constructor call.
I'm not sure exactly where it is in the docs but that's perfectly normal. Any declaration with initialization of a struct is turned into a construction call if it can. If not, it tries to treat it as a struct literal. I guess this is as close as it comes: https://dlang.org/spec/struct.html#struct-constructor "Struct constructors are used to initialize an instance of a struct when a more complex construction is needed than is allowed by static initialization or a struct literal. " Which sends you back up here: https://dlang.org/spec/struct.html#static_struct_init showing the = syntax. opAssign is only used AFTER the struct has already been declared.
Oct 03 2020