www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Sparse Aggregate Assignment/Initialization (RAII)

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
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.
Jul 07 2014
parent reply Justin Whear <justin economicmodeling.com> writes:
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
Jul 07 2014
next sibling parent reply Justin Whear <justin economicmodeling.com> writes:
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
Jul 07 2014
parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
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!
Jul 07 2014
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
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.
Jul 08 2014