Comment #0 by franklinmathieu — 2014-10-13T13:02:25Z
Given the following source:
import std.stdio;
import std.string;
class Wrapper(T) {
T val;
this(T val) { this.val = val; }
auto opDispatch(string s, T...)(T args) {
return mixin("this.val." ~ s)(args);
}
}
void main() {
auto wrap = new Wrapper!string("Lorem ipsum dolor sit amet");
foreach (e; wrap.split(" "))
writeln(e);
}
We get an error on the line with wrap.split(" "):
template std.array.split cannot deduce function from argument types !()(Wrapper!string, string), candidates are:
std.array.split(S)(S s) if (isSomeString!S)
std.array.split(R, E)(R r, E delim) if (isForwardRange!R && is(typeof(ElementType!R.init == E.init)))
std.array.split(R1, R2)(R1 r, R2 delim) if (isForwardRange!R1 && isForwardRange!R2 && is(typeof(ElementType!R1.init == ElementType!R2.init)))
std.array.split(alias isTerminator, R)(R r) if (isForwardRange!R && is(typeof(unaryFun!isTerminator(r.front))))
This happens because the compiler thinks that the call to split is a UFCS, because split resolves to the function in std.array and is of course not a member of the string type -- however, it cannot decide between the multiple overloads of split, and stops there, without calling opDispatch.
This can be seen pretty easily with the introduction of a str class:
class str {
string val;
this(string val) { this.val = val; }
string[] split(string delim) {
return std.array.split(val, delim);
}
}
and using the following main:
void main() {
auto wrap = new Wrapper!str(new str("Lorem ipsum dolor sit amet"));
foreach (e; wrap.split(" "))
writeln(e);
}
works as expected.
The issue happens regardless of the function being templated or not.
Comment #1 by robert.schadek — 2024-12-13T18:31:17Z