hasDataMember and mixin inconsistency

Olivier Grant olivier.grant at gmail.com
Sun Jan 27 03:47:51 PST 2013


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.


More information about the Digitalmars-d-learn mailing list