Jump to page: 1 2
Thread overview
How to copy object of class A to another object of class B?
Jan 28, 2015
zhmt
Jan 28, 2015
Marc Schütz
Jan 28, 2015
zhmt
Jan 28, 2015
zhmt
Jan 28, 2015
zhmt
Jan 28, 2015
Baz
Jan 28, 2015
Ali Çehreli
Jan 28, 2015
zhmt
Jan 29, 2015
zhmt
Jan 28, 2015
aldanor
Jan 28, 2015
Artur Skawina
Jan 28, 2015
Chris Williams
Jan 29, 2015
zhmt
January 28, 2015
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!!!
January 28, 2015
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).
January 28, 2015
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.
January 28, 2015
Anybody help?
January 28, 2015
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 .
January 28, 2015
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.
January 28, 2015
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
January 28, 2015
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.
January 28, 2015
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

January 28, 2015
Thx very much for all the help, I will try.
« First   ‹ Prev
1 2