www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Build an AliasSeq from memberFunction return types

reply Timoses <timosesu gmail.com> writes:
Hi,

I feel like starting to dig deeper into D. And I got lost : D.

I would like to reflect on defined bitfields:

    struct S
    {
       mixin!(bitfields!(
          <bitfieldType>, <bitfieldName>, <size>,
          ...
       ));
    }

which produces something like this in the back scenes:

    struct S
    {
       uint storage;

        property <bitfieldType> <bitfieldName>() {
          ... return field from storage;
       }
    }

There is an approach here:
https://forum.dlang.org/post/o5u21b$15f3$1 digitalmars.com
However, it feels a bit overcomplicating the issue perhaps.

To retrieve the member names the following (and filtering for 
only the functions) does the job:

    alias members = aliasSeqOf!([__traits(allMembers, S)]);

However, I now would want to build an AliasSeq of the types. My 
idea would be (absolute pseudocode!!!):

    alias memberTypes;
    static foreach (member; members)
    {
       memberTypes ~= ReturnType!S.member;
    }

    pragma(msg, memberTypes); // prints sth like: (int, bool, 
uint, ...)

I have taken a look at https://dlang.org/phobos/std_meta.html but 
am unsure whether I can actually build an AliasSeq iteratively.

The mentioned example might help:
    alias TL = AliasSeq!(int, double);
    alias Types = AliasSeq!(TL, char);
    static assert(is(Types == AliasSeq!(int, double, char)));

However, I can't simply do

    static foreach (i, member; members)
    {
       alias memberTypes_i = AliasSeq!
          (memberTypes_i, ReturnType!S.<member>) // <--- no idea 
even how to get
                                                 // the ReturnType 
here...
                                                 // S.member does 
not work
    }
    alias memberTypes = AliasSeq!(memberTypes_i_max);

But what the heck! I can't find a solution!
This might be related to:
https://forum.dlang.org/post/pxtqeahzxrsrljnrworq forum.dlang.org

Do you have any ideas? Or does your head start spinning like mine 
does, too?
Mar 09 2018
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Friday, 9 March 2018 at 17:47:46 UTC, Timoses wrote:
 To retrieve the member names the following (and filtering for 
 only the functions) does the job:

    alias members = aliasSeqOf!([__traits(allMembers, S)]);
This can be simplified to alias members = Alias!(__traits(allMembers, S));
 However, I now would want to build an AliasSeq of the types. My 
 idea would be (absolute pseudocode!!!):

    alias memberTypes;
    static foreach (member; members)
    {
       memberTypes ~= ReturnType!S.member;
    }
Generally, we use recursive templates in these cases: template GetMemberTypes(funcs...) { static if (funcs.length == 0) { alias GetMemberTypes = AliasSeq!(); } else { alias GetMemberTypes = AliasSeq!( ReturnType!(funcs[0]), GetMemberTypes!(funcs[1..$]) ); } } However, std.meta has staticMap, which will do this recursion for us: alias memberTypes = staticMap!(ReturnType, members); Of course, this assumes 'members' contains only the functions you care about. All in all, what you want can be boiled down to this code: import std.meta : staticMap, Alias, Filter; import std.traits : isFunction, ReturnType; import std.bitmanip : bitfields; struct A { int a; mixin(bitfields!( uint, "x", 2, int, "y", 3, uint, "z", 2, bool, "flag", 1)); } template GetMember(T) { alias GetMember(string name) = Alias!(__traits(getMember, T, name)); } alias memberTypes = staticMap!(ReturnType, Filter!(isFunction, staticMap!(GetMember!A, __traits(allMembers, A)))); So, how does it work? GetMember is a template that takes an aggregate type as a parameter and returns a new template that takes a string. This inner template then returns the member of the aggregate type that has that name: // Define a template that will find a member in A. alias GetMemberOfA = GetMember!A; // Get the 'flag' member of A. alias someMemberOfA = GetMemberOfA!"flag"; Next: This line is a bit of a mouthful, so let's break it down: alias memberTypes = staticMap!(ReturnType, Filter!(isFunction, staticMap!(GetMember!A, __traits(allMembers, A)))); becomes: // Grab the name of every single member of A. alias allMemberNames = Alias!(__traits(allMembers, A)); // Define a template that will find a member in A. alias GetMemberOfA = GetMember!A; // Now get the members of A that correspond to the names __traits(allMembers) returned. alias allMembers = staticMap!(GetMemberOfA, allMemberNames); // Get rid of everything that's not a function. alias onlyFunctions = Filter!(isFunction, allMembers); // And finally grab the return type of each function. alias memberTypes = staticMap!(ReturnType, onlyFunctions); -- Simen
Mar 09 2018
parent Timoses <timosesu gmail.com> writes:
I couldn't have wished for a better answer!

Thank you so much, Simen.
Mar 19 2018