www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to copy object of class A to another object of class B?

reply "zhmt" <zhmtzhmt qq.com> writes:
I have a struct created by thrift:

struct Card {
   long id;
   string pwd;
   long agentId;
   bool valid;
   long rmb;
   long createDate;
   long soldDate;
   long chargeDate;

   mixin TStructHelpers!([
     TFieldMeta(`id`, 1, TReq.OPTIONAL),
     TFieldMeta(`pwd`, 2, TReq.OPTIONAL),
     TFieldMeta(`agentId`, 3, TReq.OPTIONAL),
     TFieldMeta(`valid`, 4, TReq.OPTIONAL),
     TFieldMeta(`rmb`, 5, TReq.OPTIONAL),
     TFieldMeta(`createDate`, 6, TReq.OPTIONAL),
     TFieldMeta(`soldDate`, 7, TReq.OPTIONAL),
     TFieldMeta(`chargeDate`, 8, TReq.OPTIONAL)
   ]);
}

and another class created for hibernated:

class Card
{
	import hibernated.core;

	 Id
	 Generated
	long id;
	 UniqueKey
	string pwd;
	//index
	long agentId;
	bool valid;
	long rmb;
	long createDate;
	long soldDate;
	long chargeDate;
}


Sometime , I need to copy them:

thrift.Card tc;
....
db.Card dc;

dc.id = tc.id;
dc.pwd = tc.pwd;
...


It is boring coding, I want a solution to copy them automatically:
void copyObj(SRC,DEST)(SRC src,DEST dest)
{
	foreach (i, type; typeof(SRC.tupleof)) {
		auto name = SRC.tupleof[i].stringof;
		__traits(getMember, dest, name) =  __traits(getMember, src, 
name);
		writeln(name);
	}
}

Unfortunitely, it doesnt work,  how to improve it?

Any suggestions is welcome.
Thx ahead!!!
Jan 28 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 28 January 2015 at 09:44:29 UTC, zhmt wrote:
 It is boring coding, I want a solution to copy them 
 automatically:
 void copyObj(SRC,DEST)(SRC src,DEST dest)
 {
 	foreach (i, type; typeof(SRC.tupleof)) {
 		auto name = SRC.tupleof[i].stringof;
 		__traits(getMember, dest, name) =  __traits(getMember, src, 
 name);
 		writeln(name);
 	}
 }

 Unfortunitely, it doesnt work,  how to improve it?
Haven't tested it, but the `auto name = ...` part is likely to be the problem. By using `auto`, your declaring a runtime variable, which you then later try to use with `__traits(getMember, ...)`, which expects a value known at compile time. Try using `alias name = ...`, or if that fails, just repeat the expression `SRC.tupleof[i].stringof` wherever `name` occurs (though I'm sure there is a nicer way).
Jan 28 2015
next sibling parent reply "zhmt" <zhmtzhmt qq.com> writes:
void getT(SRC,DEST)(SRC src,DEST dest)
{
	foreach (i, type; typeof(SRC.tupleof)) {
		string name = SRC.tupleof[i].stringof;
		__traits(getMember, dest, name) =  __traits(getMember, src, 
name);
  		writeln(name);
	}
}

when I write the code above, the compile complains that:

source/app.d(14): Error: variable name cannot be read at compile 
time.
Jan 28 2015
next sibling parent reply "zhmt" <zhmtzhmt qq.com> writes:
Anybody help?
Jan 28 2015
next sibling parent "zhmt" <zhmtzhmt qq.com> writes:
The final version works well:

void copyObj(SRC,DEST)(ref SRC src,ref DEST dest)
{
	foreach (i, type; typeof(SRC.tupleof)) {
		__traits(getMember, dest, SRC.tupleof[i].stringof) =  
__traits(getMember, src, SRC.tupleof[i].stringof);
	}
}

thank u ,  Marc Schütz .
Jan 28 2015
prev sibling parent "Baz" <bb.temp gmx.com> writes:
On Wednesday, 28 January 2015 at 14:35:58 UTC, zhmt wrote:
 Anybody help?
__Traits functions are evaluated at compile time so it's not as simple. The best you can do is to generate a string to mixin based on the aggragate members. here i have an example of how you can iterate through the members: https://github.com/BBasile/Iz/blob/master/import/iz/traits.d#L18 Writing an opAssign() operator will be as fast, you just need to remember to keep it in sync with the classe members. You could also generate the struct programmatically, based on the classes declaration.
Jan 28 2015
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
name must be 'enum':

On 01/28/2015 06:34 AM, zhmt wrote:
 void getT(SRC,DEST)(SRC src,DEST dest)
 {
      foreach (i, type; typeof(SRC.tupleof)) {
          string name = SRC.tupleof[i].stringof;
enum name = SRC.tupleof[i].stringof;
          __traits(getMember, dest, name) =  __traits(getMember, src, name);
           writeln(name);
      }
 }

 when I write the code above, the compile complains that:

 source/app.d(14): Error: variable name cannot be read at compile time.
Ali
Jan 28 2015
next sibling parent "zhmt" <zhmtzhmt qq.com> writes:
Thx very much for all the help, I will try.
Jan 28 2015
prev sibling parent "zhmt" <zhmtzhmt qq.com> writes:
On Wednesday, 28 January 2015 at 14:59:52 UTC, Ali Çehreli wrote:
 name must be 'enum':

 On 01/28/2015 06:34 AM, zhmt wrote:
 void getT(SRC,DEST)(SRC src,DEST dest)
 {
     foreach (i, type; typeof(SRC.tupleof)) {
         string name = SRC.tupleof[i].stringof;
enum name = SRC.tupleof[i].stringof;
         __traits(getMember, dest, name) =  __traits(getMember, 
 src, name);
          writeln(name);
     }
 }

 when I write the code above, the compile complains that:

 source/app.d(14): Error: variable name cannot be read at 
 compile time.
Ali
Ali, I have test the enum name declaration, it works well, Thx for your help.
Jan 28 2015
prev sibling parent "aldanor" <i.s.smirnov gmail.com> writes:
On Wednesday, 28 January 2015 at 11:30:13 UTC, Marc Schütz wrote:
 On Wednesday, 28 January 2015 at 09:44:29 UTC, zhmt wrote:
 It is boring coding, I want a solution to copy them 
 automatically:
 void copyObj(SRC,DEST)(SRC src,DEST dest)
 {
 	foreach (i, type; typeof(SRC.tupleof)) {
 		auto name = SRC.tupleof[i].stringof;
 		__traits(getMember, dest, name) =  __traits(getMember, src, 
 name);
 		writeln(name);
 	}
 }

 Unfortunitely, it doesnt work,  how to improve it?
Haven't tested it, but the `auto name = ...` part is likely to be the problem. By using `auto`, your declaring a runtime variable, which you then later try to use with `__traits(getMember, ...)`, which expects a value known at compile time. Try using `alias name = ...`, or if that fails, just repeat the expression `SRC.tupleof[i].stringof` wherever `name` occurs (though I'm sure there is a nicer way).
And if the alias doesn't work directly, you can always use a well-known hack: alias Alias(T) = T; alias Alias(alias T) = T; so then this works: alias member = Alias!(__traits(getMember, Parent, "child")); Idk if it's a feature or a bug of how getMember works but I had to use this numerous times.
Jan 28 2015
prev sibling next sibling parent Artur Skawina via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On 01/28/15 10:44, zhmt via Digitalmars-d-learn wrote:
 I have a struct created by thrift:
 
 struct Card {
   long id;
   string pwd;
   long agentId;
   bool valid;
   long rmb;
   long createDate;
   long soldDate;
   long chargeDate;
 
   mixin TStructHelpers!([
     TFieldMeta(`id`, 1, TReq.OPTIONAL),
     TFieldMeta(`pwd`, 2, TReq.OPTIONAL),
     TFieldMeta(`agentId`, 3, TReq.OPTIONAL),
     TFieldMeta(`valid`, 4, TReq.OPTIONAL),
     TFieldMeta(`rmb`, 5, TReq.OPTIONAL),
     TFieldMeta(`createDate`, 6, TReq.OPTIONAL),
     TFieldMeta(`soldDate`, 7, TReq.OPTIONAL),
     TFieldMeta(`chargeDate`, 8, TReq.OPTIONAL)
   ]);
 }
 
 and another class created for hibernated:
 
 class Card
 {
     import hibernated.core;
 
      Id
      Generated
     long id;
      UniqueKey
     string pwd;
     //index
     long agentId;
     bool valid;
     long rmb;
     long createDate;
     long soldDate;
     long chargeDate;
 }
 
 
 Sometime , I need to copy them:
 
 thrift.Card tc;
 ....
 db.Card dc;
 
 dc.id = tc.id;
 dc.pwd = tc.pwd;
 ...
 
 
 It is boring coding, I want a solution to copy them automatically:
You could just add a method to the db class: void fields(B)(auto ref B b) property { foreach (I, _; typeof(this.tupleof)) this.tupleof[I] = mixin(`b.`~__traits(identifier, this.tupleof[I])); } then dc.fields = tc; will work. artur
Jan 28 2015
prev sibling parent reply "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
On Wednesday, 28 January 2015 at 09:44:29 UTC, zhmt wrote:
 Sometime , I need to copy them:

 thrift.Card tc;
 ....
 db.Card dc;

 dc.id = tc.id;
 dc.pwd = tc.pwd;
 ...


 It is boring coding, I want a solution to copy them 
 automatically:
 void copyObj(SRC,DEST)(SRC src,DEST dest)
 {
 	foreach (i, type; typeof(SRC.tupleof)) {
 		auto name = SRC.tupleof[i].stringof;
 		__traits(getMember, dest, name) =  __traits(getMember, src, 
 name);
 		writeln(name);
 	}
 }

 Unfortunitely, it doesnt work,  how to improve it?
Assuming that the hibernated class isn't auto-generated and you can redefine its contents freely, the following style may be an alternative that works for you: struct Foo { public: string a; int b; } class FooClass { public: union { struct { string a; int b; }; Foo foo; } } void main() { Foo f = Foo("a", 10); FooClass c = new FooClass(); c.foo = f; writefln("%s %s", c.a, c.b); } Probably the anonymous struct will break the UDAs, but it should be worth testing.
Jan 28 2015
parent "zhmt" <zhmtzhmt qq.com> writes:
On Wednesday, 28 January 2015 at 23:34:10 UTC, Chris Williams 
wrote:
 On Wednesday, 28 January 2015 at 09:44:29 UTC, zhmt wrote:
 Sometime , I need to copy them:

 thrift.Card tc;
 ....
 db.Card dc;

 dc.id = tc.id;
 dc.pwd = tc.pwd;
 ...


 It is boring coding, I want a solution to copy them 
 automatically:
 void copyObj(SRC,DEST)(SRC src,DEST dest)
 {
 	foreach (i, type; typeof(SRC.tupleof)) {
 		auto name = SRC.tupleof[i].stringof;
 		__traits(getMember, dest, name) =  __traits(getMember, src, 
 name);
 		writeln(name);
 	}
 }

 Unfortunitely, it doesnt work,  how to improve it?
Assuming that the hibernated class isn't auto-generated and you can redefine its contents freely, the following style may be an alternative that works for you: struct Foo { public: string a; int b; } class FooClass { public: union { struct { string a; int b; }; Foo foo; } } void main() { Foo f = Foo("a", 10); FooClass c = new FooClass(); c.foo = f; writefln("%s %s", c.a, c.b); } Probably the anonymous struct will break the UDAs, but it should be worth testing.
The hibernated class is not auto-generated yet. I think this is a good idea too.
Jan 28 2015