hasDataMember and mixin inconsistency

Olivier Grant olivier.grant at gmail.com
Sun Jan 27 07:22:26 PST 2013


On Sunday, 27 January 2013 at 12:58:39 UTC, Philippe Sigaud wrote:
>>> 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.
>
> ? I'll find the files again, for I tested before posting.
>
>>> 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.
>
> Test is inside main() { ... }. I guess it's not visible from the
> module inner scope.
>
>
>>> 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.
>
> ?
>
> Here is what I used before posting:
>
> string hasDataMember( T )(string M )
> {
>     return " __traits(compiles, {
>         Test t;
>         auto _ = t.D; // reading t.M
>         t." ~ M ~ " = t." ~ M ~ "; // assign to t.M
>     })";
> }

What is the purpose of "auto _ = t.D;" ?

> void main()
> {
>    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(!mixin(hasDataMember!(Test)("init"))); // (1) - Fails
>    assert(!mixin(hasDataMember!(int)("init"))); // (2) - Fails
>
>    assert(!mixin(hasDataMember!(Test)("A")));
>    assert(!mixin(hasDataMember!(Test)("B")));
>    assert(!mixin(hasDataMember!(Test)("C")));
>
>    assert(mixin(hasDataMember!(Test)("D")));
>    assert(mixin(hasDataMember!(Test)("E")));
>    assert(mixin(hasDataMember!(Test)("F")));
> }
>
> It seems the right behaviour. Am I mistaken?

Using dmd 2.060 and command line "rdmd test.d", I get an 
assertion fail on both calls that check for a member "init" 
whether for int or Test.


More information about the Digitalmars-d-learn mailing list