Thread overview
Sparse Aggregate Assignment/Initialization (RAII)
Jul 07, 2014
Nordlöw
Jul 07, 2014
Justin Whear
Jul 07, 2014
Justin Whear
Jul 08, 2014
Nordlöw
Jul 08, 2014
Marc Schütz
July 07, 2014
Because D currently doesn't support RAII using named parameters like in Python I tried the following.

Say I have an aggregate

class C { int x,y,z,w; }

or similarly

struct C { int x,y,z,w; }

I know define a generic _free_ function

ref T set(string member, T, U)(ref T a, in U value) if (isAggregateType!T &&
                                                        hasMember!(T, member))
{
    mixin(`a.` ~ member ~ ` = value;`);
    return a;
}

which I want to use for flexible initialization of several members at once.

However using this function through UFCS

    auto cx = new C().set!"x"(11);

fails as

algorithm_ex.d(1257,17): Error: template algorithm_ex.set cannot deduce function from argument types !("x")(C, int), candidates are:
algorithm_ex.d(1242,7):        algorithm_ex.set(string member, T, U)(ref T a, in U value) if (isAggregateType!T && hasMember!(T, member))

Instead I have to use

    auto c = new C(); set!"x"(c, 11);

which is not as elegant.

Why doesn't UCFS work here and is there a solution using DMD git master?

Further Is there a cleverer way to do this without resorting to mixins?

This old post

http://forum.dlang.org/thread/mailman.2966.1301533296.4748.digitalmars-d-learn@puremagic.com

talks about opDispatch() but, to my knowledge, it requires the aggregate to have extra members doing the initialization.

I want this because I've identified in some parts of my code that I have large structures were only a few of the elements are initialized to non-default values.
July 07, 2014
On Mon, 07 Jul 2014 21:34:05 +0000, Nordlöw wrote:

> However using this function through UFCS
> 
>      auto cx = new C().set!"x"(11);
> 
> fails as
> 
> algorithm_ex.d(1257,17): Error: template algorithm_ex.set cannot deduce
> function from argument types !("x")(C, int), candidates are:
> algorithm_ex.d(1242,7):        algorithm_ex.set(string member, T,
> U)(ref T a, in U value) if (isAggregateType!T && hasMember!(T,
> member))
> 
> Instead I have to use
> 
>      auto c = new C(); set!"x"(c, 11);
> 
> which is not as elegant.
> 
> Why doesn't UCFS work here and is there a solution using DMD git master?

You need to use `auto ref` to have this work with both classes and
structs.  A working version of your code here: auto dx = D().set!"x"(11);
	assert(dx.x == 11);

On Mon, 07 Jul 2014 21:34:05 +0000, Nordlöw wrote:
> Further Is there a cleverer way to do this without resorting to mixins?

__traits(getMember, ...) is useful here, see this version of your code: http://dpaste.dzfl.pl/75e03fbec020
July 07, 2014
On Mon, 07 Jul 2014 21:49:22 +0000, Justin Whear wrote:

> On Mon, 07 Jul 2014 21:34:05 +0000, Nordlöw wrote:
> 
>> However using this function through UFCS
>> 
>>      auto cx = new C().set!"x"(11);
>> 
>> fails as
>> 
>> algorithm_ex.d(1257,17): Error: template algorithm_ex.set cannot deduce
>> function from argument types !("x")(C, int), candidates are:
>> algorithm_ex.d(1242,7):        algorithm_ex.set(string member, T,
>> U)(ref T a, in U value) if (isAggregateType!T && hasMember!(T,
>> member))
>> 
>> Instead I have to use
>> 
>>      auto c = new C(); set!"x"(c, 11);
>> 
>> which is not as elegant.
>> 
>> Why doesn't UCFS work here and is there a solution using DMD git master?
> 
> You need to use `auto ref` to have this work with both classes and
> structs.  A working version of your code here: auto dx =
> D().set!"x"(11);
> 	assert(dx.x == 11);

Copy and paste gone astray; should be this link: http://dpaste.dzfl.pl/3c33ad70040f
July 08, 2014
On Monday, 7 July 2014 at 21:50:22 UTC, Justin Whear wrote:
> Copy and paste gone astray; should be this link:
> http://dpaste.dzfl.pl/3c33ad70040f

Thx!
July 08, 2014
On Monday, 7 July 2014 at 21:49:22 UTC, Justin Whear wrote:
> On Mon, 07 Jul 2014 21:34:05 +0000, Nordlöw wrote:
>
>> However using this function through UFCS
>> 
>>      auto cx = new C().set!"x"(11);
>> 
>> fails as
>> 
>> algorithm_ex.d(1257,17): Error: template algorithm_ex.set cannot deduce
>> function from argument types !("x")(C, int), candidates are:
>> algorithm_ex.d(1242,7):        algorithm_ex.set(string member, T,
>> U)(ref T a, in U value) if (isAggregateType!T && hasMember!(T,
>> member))
>> 
>> Instead I have to use
>> 
>>      auto c = new C(); set!"x"(c, 11);
>> 
>> which is not as elegant.
>> 
>> Why doesn't UCFS work here and is there a solution using DMD git master?
>
> You need to use `auto ref` to have this work with both classes and
> structs.  A working version of your code here: auto dx = D().set!"x"(11);
> 	assert(dx.x == 11);

To elaborate:
`new C()` is an r-value, and references can only be taken from l-values.