www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Strange behavior with opAssign and static if

reply Andre <andre s-e-a-p.de> writes:
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);
		}
	}
}
Feb 08 2014
parent reply "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
__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;
		}
	}
}
Feb 08 2014
parent Andre <andre s-e-a-p.de> writes:
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;
          }
      }
 }
Feb 08 2014