www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opDispatch and UFCS

reply John Colvin <john.loughran.colvin gmail.com> writes:
struct S
{
     int a;
     template opDispatch(string s)
     {
         template opDispatch(T...)
         {
             auto ref opDispatch(Args ...)(auto ref Args args)
             {
                 return S(mixin(`a.` ~ s ~ (T.length ? `!T` : ``) 
~ `(args)`));
             }
         }
     }
}

int foo(int a, int b)
{
     return a + b;
}

S bar(S s, int b)
{
     return S(s.a - b);
}

unittest
{
     auto s = S(3);
     s = s.bar(1);
     assert(s.a == 2);
     s = s.foo(1);
     assert(s.a == 3);
}

this gives me:

test.d-mixin-10(10): Error: function opdispatchtest.bar (S s, int 
b) is not callable using argument types (int, int)
test.d(29): Error: template instance 
test.S.opDispatch!"bar".opDispatch!().opDispatch!int error 
instantiating

Bug? Or am I misunderstanding how these two features are supposed 
to interact?
May 11 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 11 May 2016 at 23:46:48 UTC, John Colvin wrote:
 Bug? Or am I misunderstanding how these two features are 
 supposed to interact?
I'm not sure what you actually expected there, but I'd note that in general, opDispatch will always be preferred over UFCS, just like any other member access, so if you have an unrestricted opDispatch, you basically disable ufcs on the type.
May 11 2016
parent John Colvin <john.loughran.colvin gmail.com> writes:
On Thursday, 12 May 2016 at 00:04:43 UTC, Adam D. Ruppe wrote:
 On Wednesday, 11 May 2016 at 23:46:48 UTC, John Colvin wrote:
 Bug? Or am I misunderstanding how these two features are 
 supposed to interact?
I'm not sure what you actually expected there, but I'd note that in general, opDispatch will always be preferred over UFCS, just like any other member access, so if you have an unrestricted opDispatch, you basically disable ufcs on the type.
I think I was hoping that the opDispatch wouldn't compile in the second case and it would therefore fail-over to UFCS. std.typecons.Proxy (and therefore Typedef) seems to get around this: import std.typecons; alias Blah = Typedef!(int); void foo(Blah a){} void main() { Blah.init.foo; } work fine.
May 11 2016