What are the recommended guidelines for using/not using UFCS in writing generic libraries?

I ask because if you have an internal generic free function that you use on types in a generic algorithm via ufcs, then everything works fine until the type being operated on has a member function with a similar name.

If the signature matches the free function then the member function is called instead of the free function (silently) and if the signature does not match then you get a compiler error.

I.e.:

auto identity(T)(T t) { return t; }
auto fun(T)(T t) {
    return t.identity;
}

void main() {
    fun(3).writeln; // ok, print 3

    struct S1 {}
    fun(S1()).writeln; // ok, prints S1()

    struct S2 { int identity() { return 77; } }
    fun(S2()).writeln; // silent hijack, prints 77

    struct S3 { int identity(int i) { return i + 2; } }
    fun(S3()).writeln; // compile error
}

So the problem is that fun wants to use a utility function that it knows about, but it turns out that T can hijack that internal, private, utility if you use ufcs.

So basically, it seems like ufcs is fun until it doesn't work, and it's not really obvious that you can run in to these problems with ufcs.

I feel like the last case where it's a compilation error should maybe be ok though, since the function being called is actually undefined so ufcs should kick in. The problem as I understand it is that ufcs is not part of an overload set. Making it part of it would not prevent the silent hijack, but would remove the compilation problem.

Is there something I'm not seeing as to why UFCS is not part of the overload set, and is there a way other than not using UFCS to prevent the silent hijacking?

Cheers
- Ali

Reply via email to