Hi,

First of all, I am very new to D as I've just been playing around with it for the last week, so I might be missing something very obvious.

I'm trying to write a template that would allow me to determine if a struct or class has a data member with a specific name (similar to what the hasMember template does, but only for data members).

I originally wrote the following template :

[code]
template hasDataMember( T, string M )
{
   enum hasDataMember = __traits(
      compiles,
      mixin("( ref T x, ref T y ){ x." ~ M ~ " = y." ~ M ~ "; }")
   );
}

unittest
{
   struct Test
   {
      struct A { }
      void B( ) { }

      @property A C( ) const { return F; }
      @property long D( ) const { return E; }
      @property void D( long e ) { E = e; }

      long E;
      A F;
   }

   assert(!hasDataMember!(int,"A"));
   assert(!hasDataMember!(int,"init"));

   //assert(!hasDataMember!(Test,"init")); // This fails, why?
   assert(!hasDataMember!(Test,"A"));
   assert(!hasDataMember!(Test,"B"));
   assert(!hasDataMember!(Test,"C"));
   assert( hasDataMember!(Test,"D"));
   assert( hasDataMember!(Test,"E"));
   assert( hasDataMember!(Test,"F"));
}
[/code]

And it works pretty well, but it gets the wrong result for the following test case which is commented out. Originally, I thought maybe you were allowed to write to the .init member of structures, but writing the same code directly without relying on a mixin actually yields the right result (all the asserts pass):

[code]
struct A { int b_; }
assert(!__traits(compiles,( ref int x, ref int y ){ x.init = y.init; })); assert(!__traits(compiles,( ref Test0 x, ref Test0 y ){ x.init = y.init; })); assert( __traits(compiles,( ref Test0 x, ref Test0 y ){ x.b_ = y.b_; }));
[/code]

So I have two questions :
1) Why is there this inconsistency between the mixin and direct version ? 2) Is there a better way to check for the existence of a data member ?

Best regards,

Olivier.

Reply via email to