[DIP] In-place struct initialization

ZombineDev via Digitalmars-d digitalmars-d at puremagic.com
Thu Aug 4 00:22:27 PDT 2016


On Thursday, 4 August 2016 at 05:15:56 UTC, Patrick Schluter 
wrote:
> On Wednesday, 3 August 2016 at 21:35:58 UTC, ZombineDev wrote:
>> On Wednesday, 3 August 2016 at 20:30:07 UTC, deadalnix wrote:
>>> On Sunday, 31 July 2016 at 14:38:33 UTC, Lodovico Giaretta 
>>> wrote:
>>>> I support this idea of extending curly-brace initializers. 
>>>> It would be very useful and less ambiguous than 
>>>> parenthesized initializers.
>>>>
>>>
>>> Curly braces are already extremely overloaded. They can start 
>>> a block statement, a delegate literal, a struct literal and 
>>> I'm sure I forgot something.
>>
>> Is there a better choice? StructInitializer [1] is already 
>> part of the grammar.
>> It would be inconsistent to use anything else, e.g.
>>
>> S x = { a:1, b:2}; // already works
>> x = { a:3, b:4};   // why shouldn't this work?
>>
>> [1]: http://dlang.org/spec/grammar.html#StructInitializer
>
> To come back to C. It doesn't work in C either. The second 
> expression is ambiguous as there could be several structs that 
> match the initialiser.

Why would there be any ambiguity? It doesn't matter if more than 
one structs have the syntactically identical initializers, 
because the intended type is clearly the type of the variable 
that we're assigning to.

> In the first expression the type is deduced from the 
> declaration. That's why the compound literal was introduced 
> which is in fact the explicit mention of the type by 
> typecasting. So in C the above will become:
>
> S x = { a:1, b:2}; // already works
> x = (struct S){ a:3, b:4};   // C99 compound statement
> which allows automatically to be passed to a function call
> f((struct S){ a:3, b:4});
>
> D has a lot of smart type inference rules but I don't think 
> that a little redundancy here or there should be avoided 
> (especially since D already has quite a tendency to require a 
> lot of casting).

Maybe I didn't mention it, but I think that { a: 1, b: 2 } syntax 
should only be allowed when there is no ambiguity. For example, 
if a function is overloaded the type would need to be specified 
to disambiguate the function call:

void f(S1);
void f(S2);

f(S1 { a: 1, b: 2 });

s = S2 { a: 1, b: 2 }; // s's opAssign accepts both S1 and S2

> This said, in C++ compound initialiser are implemented in some 
> compiler as extension and are really problematic (object life 
> time) and it would be probably similar in D

I would be interested to hear more about that. My (maybe naive) 
understanding tells me that there shouldn't be any problems:

s = S1 { a: 1, b: 2 };

// would be lowered to:

{
   S1 __tmp1 = { a: 1, b: 2 };
   s.opAssign(__tmp1);
   __tmp1.~this(); // dtor is called as usual
}

So it's up to the authot of the struct to ensure correct 
application of the RAII idiom, which is not different from:


s = S1(1, 2);

// would be lowered to:

{
   S1 __tmp1 = S1(1, 2);
   s.opAssign(__tmp1);
   __tmp1.~this(); // dtor is called as usual
}







More information about the Digitalmars-d mailing list