Eldar Insafutdinov wrote: > Currently we have ParameterTypeTuple for extracting type list of function > arguments. This is not enough. There should be a clean way to extract storage > classes and default arguments if there are any. Any thoughts?
Parsing stringof is not required. There's a trick (see tools.base.[isRef, refToParamList, refToValueList]) that involves "sliding" a constant value over the parameter list and seeing if it works (if not, it's ref). ------------------- Example usage: struct YWrapper(C) { C callable; alias Ret!(C) R; mixin("R opCall("~ refToParamList("" /* no leading parameter */, "Params!(C)[1 .. $]" /* types to check */, isRef!(C)[1 .. $] /* refness string */)~ ") { return callable(&opCall"~ refToValueList("," /* &opCall comes first, lead with comma */, isRef!(C)[1 .. $])~ "); }" ); } ------------------- The complete relevant code: struct __isRef(C, size_t which) { alias ParameterTypeTuple!(C) pt; pt[0..which] pre; const pt[which] test; pt[which+1..$] post; const bool r = !is(typeof(C(pre, test, post))); } template _isRef(C, size_t which) { static if (__isRef!(C, which).r) const char _isRef='t'; else const char _isRef='f'; } string refliteral(int len) { char[] res; for (int i=0; i<len; ++i) { res~="~_isRef!(C, "~ctToString(i)~")"; } return "\"\""~res; } template isRef(C) { const string isRef=mixin(refliteral(Params!(C).length)); } string refToParamList(string lead, string TUP, string refs) { string res; for (int i=0; i<refs.length; ++i) { if (refs[i]=='t') res~="ref "; res~=TUP~"["~ctToString(i)~"] param_"~ctToString(i); if (i<refs.length-1) res~=", "; } return res; } string refToValueList(string lead, string refs) { string res=""; for (int i=0; i<refs.length; ++i) { if (i) res ~= ", "; else res ~= lead; res~="param_"~ctToString(i); } return res; }