On Sunday, 27 January 2013 at 09:49:33 UTC, Philippe Sigaud wrote:
Hi,

If think in your code, your testing whether or a not a mixin("...")
statement is valid D. Which it is.

But what I'm surprised by is that the behavior of hasDataMember
with my implementation works fine for all test cases except
hasDataMember!(Test, "init"). If it was only testing whether the
mixin statement was well formed or not, shouldn't my
implementation of hasDataMember always return true ? What's more
confusing is that it seems to work properly for all test cases
except a built-in property of a structure :

assert(!hasDataMember!(long, "init")); // This succeeds.
assert(!hasDataMember!(Test, "init")); // This fails.

I'd put the mixin externally:

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

I've just tried that and it unfortunately does not work, the same
test case still fails.

Also, I suppose the Test inner struct is not visible from the
hasDataMember template. The template is instantiated where it's
declared, not where it's called. You could use a mixin template, I
guess.

I'm not sure at all what you mean by that. I thought all symbols
within a source file were visible irrespective of their order or
scope? Also, the test failure is on the Test structure directly,
not its inner structure A.

I'd use a string mixin, but then I was converted to string mixins a
few years ago :)

string hasDataMember( T )(string M )
{
    return " __traits(compiles, {
        Test t;
        auto _ = t.D; // reading t.M
        t." ~ M ~ " = t." ~ M ~ "; // assign to t.M
    })";
}

using is a bit more noisy than your solution: mixin(hadDataMember!(Test)("M"))

I've tried that as well and it still fails on the same test case
again.

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)

You cannot write to .init, it's not a member. It's a built-in
property, like .sizeof or .offsetof.

Makes sense.

2) Is there a better way to check for the existence of a data member ?

If by data member, you mean some symbol that can be read and written to, then I'd test just that. See the string mixin before: it tests for
existence, reading and writing.

Could this be a compiler bug by any chance? It seems really weird
that the template would work for intrinsic types but not for
structure, especially when the exact same template without the
use of mixin works fine.

Thanks again for your help.

Reply via email to