www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - listing template function overloads for use in compile time decisions

reply "Atash" <nope nope.nope> writes:
Let's say that we have a struct `A` that contains some template 
function named `fn` template-parameterized on its argument types:

struct A {
...
void fn(A)(auto ref A a) { ... }
...
}

I cannot get a handle on `fn` as an alias when searching for 
overloads of the string "fn" in `A` via 
`__traits(getOverloads,A,"fn")`. This makes sense, obviously, 
because `fn` doesn't really 'exist' as a template.

But the compiler can, nevertheless, generate a proper 
implementation of `fn` depending on its argument(s). It doesn't 
have to create the code, as with e.g. `__traits(compiles, 
A.init.fn(0))`. While it doesn't make sense to list overloads of 
a given name when they're templates, it does make sense that 
given some argument types and qualifiers all candidate functions 
can be easily enumerated. I can't find such a feature, however.

Moreover, I cannot figure out how one could acquire a handle on 
even *just* the best match for a given function name with some 
given argument types.

With this, library writers could perform their own overload 
resolution without enforcing the use of wrapper classes when 
trying to plug one library into another library, ex. lib A has 
struct A with `fn` and lib B has struct B with `fn` and they have 
functions `fn` that accept each other and we want to choose the 
one that partially specializes on the other over the one that 
doesn't. It's basically the decision process behind the rewriting 
that occurs with a.opCmp(b) vs. b.opCmp(a), but fully emulated in 
the presence of templates without extra client-code-side hints 
and taking into account granularity finer than the four levels of 
overload resolution. It moves glue-code (or glue-behavior like 
argument ordering to a library function) from the user to the 
library writer, and allows that glue-code to be generic.

Is this a facility that is present in D, and I missed it? Are any 
of the above bulleted use-cases manageable with present-day D?

I'm kind of an obsessive metaprogramming-fiend, so this little 
issue is strangely vexing. I've come up with an idea for a 
solution, and am attempting to implement it, but it's 
extraordinarily hackish. It assumes that the name `fn` when 
called can be entirely resolved with its arguments by looking at 
the arguments' types and their template parameters (if any) and 
implicit target conversions (and their template parameters [if 
any]). I'm seeing in my head a combinatoric blow-up from the 
possible orderings of template arguments in the template 
declaration of `fn`, so... yeah. Kinda would like a __traits 
thing that gets all possible resolutions of a symbol in a call 
expression.

Thanks for your time~!
Apr 28 2014
parent "Atash" <nope nope.nope> writes:
On Tuesday, 29 April 2014 at 06:22:34 UTC, Atash wrote:
 Let's say that we have a struct `A` that contains some template 
 function named `fn` template-parameterized on its argument 
 types:

 struct A {
 ...
 void fn(A)(auto ref A a) { ... }
 ...
 }

 I cannot get a handle on `fn` as an alias when searching for 
 overloads of the string "fn" in `A` via 
 `__traits(getOverloads,A,"fn")`. This makes sense, obviously, 
 because `fn` doesn't really 'exist' as a template.

 But the compiler can, nevertheless, generate a proper 
 implementation of `fn` depending on its argument(s). It doesn't 
 have to create the code, as with e.g. `__traits(compiles, 
 A.init.fn(0))`. While it doesn't make sense to list overloads 
 of a given name when they're templates, it does make sense that 
 given some argument types and qualifiers all candidate 
 functions can be easily enumerated. I can't find such a 
 feature, however.

 Moreover, I cannot figure out how one could acquire a handle on 
 even *just* the best match for a given function name with some 
 given argument types.

 With this, library writers could perform their own overload 
 resolution without enforcing the use of wrapper classes when 
 trying to plug one library into another library, ex. lib A has 
 struct A with `fn` and lib B has struct B with `fn` and they 
 have functions `fn` that accept each other and we want to 
 choose the one that partially specializes on the other over the 
 one that doesn't. It's basically the decision process behind 
 the rewriting that occurs with a.opCmp(b) vs. b.opCmp(a), but 
 fully emulated in the presence of templates without extra 
 client-code-side hints and taking into account granularity 
 finer than the four levels of overload resolution. It moves 
 glue-code (or glue-behavior like argument ordering to a library 
 function) from the user to the library writer, and allows that 
 glue-code to be generic.

 Is this a facility that is present in D, and I missed it? Are 
 any of the above bulleted use-cases manageable with present-day 
 D?

 I'm kind of an obsessive metaprogramming-fiend, so this little 
 issue is strangely vexing. I've come up with an idea for a 
 solution, and am attempting to implement it, but it's 
 extraordinarily hackish. It assumes that the name `fn` when 
 called can be entirely resolved with its arguments by looking 
 at the arguments' types and their template parameters (if any) 
 and implicit target conversions (and their template parameters 
 [if any]). I'm seeing in my head a combinatoric blow-up from 
 the possible orderings of template arguments in the template 
 declaration of `fn`, so... yeah. Kinda would like a __traits 
 thing that gets all possible resolutions of a symbol in a call 
 expression.

 Thanks for your time~!
Ignore the 'bulleted' bit. I edited that preceding section from a list to a paragraph.
Apr 28 2014