opDispatch and @property setters

Lodovico Giaretta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jun 21 13:48:38 PDT 2016


Hi,

I'm trying to achieve perfect forwarding of any invocation from 
the wrapper to the wrapped item, but I'm having a bad time with 
@property.

Suppose this is my wrapper (with all logic stripped):

     struct Wrapper(T)
     {
         private T wrapped;

         template hasAssignableProperty(string name, Arg)
         {
             enum bool hasAssignableProperty = is(typeof(
             (ref T val, ref Arg arg)
             {
                 mixin("val." ~ name ~ " = arg;");
             }));
         }

         @property void opDispatch(string name, Arg)(Arg arg)
             if (hasAssignableProperty!(name, Arg))
         {
             pragma(msg, "@property ", name, " ", Arg);
             mixin("return wrapped." ~ name ~ " = arg;");
         }
         auto opDispatch(string name, Args...)(Args args)
         {
             static if (Args.length > 0)
             {
                 pragma(msg, name, " ", Args);
                 mixin("return wrapped." ~ name ~ "(args);");
             }
             else
             {
                 pragma(msg, name);
                 mixin("return wrapped." ~ name ~ ";");
             }
         }
     }

It correctly handles any property, but the existence of the 
@property setter dispatcher makes me unable to use any method 
that accepts just one parameter, because the compiler tries to 
resolve it with the first opDispatch overload, misinterpreting it 
as a setter call.

Here is an example:

     struct Foo
     {
         private int _x;
         @property int x() { return _x; }
         @property void x(int newx) { _x = newx; }

         long foo(string a, double b) const { return 0; }
         void bar() {}
         int baz(int val) { return val; } // <-- method with 
exactly one argument
     }

     void main()
     {
         alias WrappedFoo = Wrapper!Foo;
         WrappedFoo wf;

         wf.x = 3;
         assert(wf.x == 3);

         long foores = wf.foo("hello", 3.14);
         wf.bar;

         int bazres = wf.baz(42); // ERROR: no property 'baz' 
(it's trying to use the first opDispatch overload, while the 
second would be ok)
     }

Any way around this issue?

Thank you in advance, and sorry if the question is silly and I'm 
just missing something stupid.

Lodovico Giaretta


More information about the Digitalmars-d-learn mailing list