digitalmars.D.learn - Build an AliasSeq from memberFunction return types
- Timoses (56/56) Mar 09 2018 Hi,
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (64/74) Mar 09 2018 This can be simplified to
- Timoses (2/2) Mar 19 2018 I couldn't have wished for a better answer!
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
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
I couldn't have wished for a better answer! Thank you so much, Simen.
Mar 19 2018