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. Anyway, I've been able to make the following work for selecting overloads of member functions: import std.traits, std.stdio; struct S { void foo(int i, double d) { writeln("Overload 1"); } void foo(double d, int i) { writeln("Overload 2"); } void test() { alias selectOverload!(S, "foo", int, double) bar; bar(1, 3.0); // Prints "Overload 1" alias selectOverload!(S, "foo", double, int) baz; baz(4.0, 2); // Prints "Overload 2" } } void main() { S s; s.test(); } template selectOverload(T, string fun, Params...) { alias selectOverloadImpl!(Params.length, Params, __traits(getOverloads, T, 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 .. $]); }