www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 13611] New: opDispatch and UFCS not resolving as expected


          Issue ID: 13611
           Summary: opDispatch and UFCS not resolving as expected
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P1
         Component: DMD
          Assignee: nobody puremagic.com
          Reporter: franklinmathieu gmail.com

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(" "))

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 &&

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(" "))

works as expected.

The issue happens regardless of the function being templated or not.

Oct 13 2014