TDPL: Overloading template functions
Philippe Sigaud
philippe.sigaud at gmail.com
Fri Jul 30 15:04:22 PDT 2010
First, trying a copy-paste of your code gives me an error in object.di
(DMD 2.047 on Windows)
C:\dmd\windows\bin\..\..\src\druntime\import\object.di|487|Error:
incompatible types for ((a) != (a2[i])): 'string' and 'immutable(char)'|
||=== Build finished: 1 errors, 0 warnings ===|
And Code::Blocks jumps me to object.di:
bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
{
if (a1.length != a2.length)
return false;
foreach(i, a; a1)
{ if (a != a2[i]) // <-- line 487. Uh oh, trying to compare strings and
chars
return false;
}
return true;
}
I had to modify it:
bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
if (is(typeof(T1.init != T2.init))) // Are T1 and T2 comparable? If not, do
not bother to compile
{
if (a1.length != a2.length) return false;
foreach(i, a; a1)
{ if (a != a2[i])
return false;
}
return true;
}
Another possibility would have it return false, but in that case, array
comparisons always compile and we lose the ability to use them as test for
instantiating a template.
I guess _ArrayEq is some internal called by the constraint, while doing the
comparison. Saving object.di and recompiling everything allows the templates
constraints to function and gives me a call to the first find.
Without the '&& false', it still calls the first find... because it still
cannot instantiate the second template:
The first find can be instantiated with T = immutable(char)[] and E =
immutable(char)[], there is nothing stopping it: T and E are the same type,
so they are trivially comparable. "two" is a valid target value for ["one",
"two"].
The second find would have T1 = immutable(char)[] and T2 = immutable(char)
and those do not compare.
testing it, find("one two three", "two") correctly calls the second version
and returns "two three".
So, maybe you just found a bug in object.di._ArrayEq. I'll post on the main
list. Anyway, for me, it seems to work, if I understand correctly what
you're doing.
Btw, if you find yourself using the same constraint regularly, you can
abstract it away in another template that returns (er, becomes, rather) a
boolean:
template areComparable(T1, T2)
{
enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous
template trick
}
And then:
T[] find(T, E)(T[] haystack, E needle)
if (areComparable!(T, E))
{
}
T[] find(T, E)(T[] longer, E[] shorter)
if (areComparable!(T, E))
{
}
Which makes for cleaner code. I renamed T1 and T2 to T and E, so showcase
the difference between the two.
Philippe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100731/3e65ca86/attachment-0001.html>
More information about the Digitalmars-d
mailing list