On Wed, 05 Jan 2011 12:07:50 +0200, Max Samukha wrote: > On 01/05/2011 11:21 AM, Lars T. Kyllingstad wrote: >> On Tue, 04 Jan 2011 17:06:45 -0600, Andrei Alexandrescu wrote: >> >>> On 1/4/11 4:49 PM, %u wrote: >>>>> There's still the risk of keeping multiple hashes. Consider: >>>> >>>>> ulong fun(ulong n) { ... } >>>>> alias memoize!fun mfun; >>>> >>>>> mfun(5); // creates hash ulong[int] >>>>> mfun(5u); // creates hash ulong[uint] mfun('5'); // creates hash >>>>> ulong[char] >>>> >>>> >>>> Ohhh I see... so you're basically looking for a compile-time version >>>> of overload resolution, right? Because things seem to be getting >>>> complicated very quickly. >>> >>> It's not that complicated; we'll be able to achieve it somehow. >>> Overloads are compile-time entities so they should be easily >>> inspectable. >> >> Since this is likely to be useful in other cases as well, maybe it >> would be better to make a general template that selects an overload? >> So you'd use it like this: >> >> alias memoize!(selectOverload!(sqrt, double)) msqrt; >> >> A first step towards this would be to make __traits(getOverloads) work >> with module-level functions. Currently it only works for member >> functions. Also it would probably be better if it accepted a function >> alias instead of a string containing the function name. > > __traits(getOverloads) does work with module level functions if you pass > a module alias to it.
Cool! I didn't know that. Here's an updated version, where selectOverload works with both module-level and member functions: module test; import std.traits, std.stdio; void foo(int i, double d) { writeln("Overload 1"); } void foo(double d, int i) { writeln("Overload 2"); } void main() { alias selectOverload!(test, "foo", int, double) bar; bar(1, 3.0); // Prints "Overload 1" alias selectOverload!(test, "foo", double, int) baz; baz(4.0, 2); // Prints "Overload 2" } template selectOverload(alias parent, string fun, Params...) { alias selectOverloadImpl!(Params.length, Params, __traits(getOverloads, parent, fun)) selectOverload; } template selectOverloadImpl(size_t lenP, A...) { static assert (A.length > lenP, "No overload matches"); static if (equalTuples!(lenP, A[0 .. lenP], ParameterTypeTuple!(A[lenP]))) { alias A[lenP] selectOverloadImpl; } else { alias selectOverloadImpl!(lenP, A[0 .. lenP], A[lenP+1 .. $]) selectOverloadImpl; } } template equalTuples(size_t len, T...) { static if (len == 0 && T.length == 0) enum equalTuples = true; else static if (T.length != len*2) enum equalTuples = false; else static if (!is (T[0] == T[len])) enum equalTuples = false; else enum equalTuples = equalTuples!(len-1, T[1 .. len], T[len+1 .. $]); }