Thread overview
Strange behavior with opAssign and static if
Feb 08, 2014
Andre
Feb 08, 2014
Stanislav Blinov
Feb 08, 2014
Andre
February 08, 2014
Hi,

I have a template structure Decimal which is used in a OrderDb structure. The opAssign method in Decimal leads to strange
behavior in the function execute();

The function execute stores the values of OrderDb in a variant
array. Decimals value should be stored as strings. There is
a static if for this condition.

There is a compilation error for the line
arr[i] = __traits(getMember, struc, member);

-> function.main.OrderDb.opAssign (OrderDb p) is not callable using argument types ()

This compilation error disappears if I remove the opAssign method
in Decimal.

How can the opAssign of Decimal influence the code path for a non
decimal field?

Kind regards
André

---code---

import std.traits: isInstanceOf;
import std.variant;

struct Decimal(int precision, int scale){
	void opAssign(T)(T d)
		if (isInstanceOf!(Decimal, T)){}

	string toString(){return "10.22";};
}

struct OrderDb{
	string orderId;
	Decimal!(10,2) amount;
}

void main(){
	execute(OrderDb());
}

void execute(T)(T struc){
	Variant[] arr = new Variant[](2);

	foreach (i, member;__traits(allMembers, T)){
		static if (isInstanceOf!(Decimal, typeof(__traits(getMember, struc, member)))){
			// Store decimals as string
			arr[i] = (__traits(getMember, struc, member)).toString();
		} else {
			// Store other values with their types
			arr[i] = __traits(getMember, struc, member);
		}
	}
}
February 08, 2014
__traits(allMembers) gives you *all* members, including methods (even implicit).
As soon as you define opAssign for your Decimal, it gets defined for OrderDb too, and then you try to assign to it :)

What you need is something like this:

void execute(T)(T struc){
	Variant[] arr = new Variant[](2);

	foreach(i, member; struc.tupleof) {
		static if (isInstanceOf!(Decimal, typeof(member))){
			// Store decimals as string
			arr[i] = member.toString();
		} else {
			// Store other values with their types
			arr[i] = member;
		}
	}
}


February 08, 2014
Thanks a lot!
This works great.

Am 08.02.2014 14:27, schrieb Stanislav Blinov:
> __traits(allMembers) gives you *all* members, including methods (even
> implicit).
> As soon as you define opAssign for your Decimal, it gets defined for
> OrderDb too, and then you try to assign to it :)
>
> What you need is something like this:
>
> void execute(T)(T struc){
>      Variant[] arr = new Variant[](2);
>
>      foreach(i, member; struc.tupleof) {
>          static if (isInstanceOf!(Decimal, typeof(member))){
>              // Store decimals as string
>              arr[i] = member.toString();
>          } else {
>              // Store other values with their types
>              arr[i] = member;
>          }
>      }
> }
>
>