Thread overview
Whats going on with this?
Oct 02, 2020
claptrap
Oct 03, 2020
claptrap
Oct 03, 2020
Daniel Kozak
Oct 03, 2020
Daniel Kozak
Oct 03, 2020
Daniel Kozak
Oct 03, 2020
Adam D. Ruppe
October 02, 2020
---
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?

October 02, 2020
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
October 03, 2020
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.

October 03, 2020
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.
October 03, 2020
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
October 03, 2020
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


October 03, 2020
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.
'''


October 03, 2020
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
October 04, 2020
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