Thread overview
What is the correct way to forward method calls to the struct field?
Jun 21, 2014
monnoroch
Jun 21, 2014
monnoroch
Jun 21, 2014
monnoroch
Jun 21, 2014
Philippe Sigaud
Jun 22, 2014
monnoroch
Jun 22, 2014
monnoroch
Jun 22, 2014
Philippe Sigaud
Jun 22, 2014
Philippe Sigaud
Jun 22, 2014
monnoroch
Jun 22, 2014
monnoroch
June 21, 2014
I tried this:

struct S {
	R opDispatch(string name, R, Args...)(Args args) {
		return mixin("(*iface)." ~ name)(iface, args);
	}
	SomeT ** iface;
}

But then val.foo(1, 2) gives me "no property 'foo' for type 'S'".

I've seen the template solution:

struct S {
	template opDispatch(string name) {
		R opDispatch(R, Args...)(Args args) {
			return mixin("(*iface)." ~ name)(iface, args);
		}
	}
	SomeT ** iface;
}

But that does not seem to work anymore.

I've tried then

struct S {
	auto ifc() {
		return *iface;
	}

	auto ifc() const {
		return *iface;
	}
	
	SomeT ** iface;
}

And that worked, but it's not perfect: i also want to pass iface
as a first argument.

val.foo(1, 2) -> (*val.iface).foo(val.iface, 1, 2).

Any suggestions?
June 21, 2014
Actyaly, last variant didn't work either: i was testing it
inside S like "ifc.foo(1)", so UFCS kiked in, not alias this.
June 21, 2014
On Saturday, 21 June 2014 at 18:16:17 UTC, monnoroch wrote:
> Actyaly, last variant didn't work either: i was testing it
> inside S like "ifc.foo(1)", so UFCS kiked in, not alias this.

Oh, my bad, "alias impl this;" actually did work. But the first
argument problem still holds.
June 21, 2014
You can use 'auto' to let the compiler deduce the return type. Here I use 'foo' which returns an int and 'bar', which returns void.

struct SomeT {
    int foo(double d) { return 0;}
    void bar(double d) { return;}
}

struct S {
    auto /* here */
       opDispatch(string name, Args...)(Args args) {
        return mixin("(*iface)." ~ name)(args);
    }
    SomeT** iface;
}


void main()
{
  SomeT st;
  SomeT* st_p = &st;
  SomeT** st_p_p = &st_p;

  S s = S(st_p_p);

  import std.stdio : writeln;
  writeln(s.foo(3.14)); // "0"
  writeln(typeof(s.bar(3.14)).stringof); // "void"
}

On Sat, Jun 21, 2014 at 8:21 PM, monnoroch via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
> On Saturday, 21 June 2014 at 18:16:17 UTC, monnoroch wrote:
>>
>> Actyaly, last variant didn't work either: i was testing it inside S like "ifc.foo(1)", so UFCS kiked in, not alias this.
>
>
> Oh, my bad, "alias impl this;" actually did work. But the first argument problem still holds.
June 22, 2014
Thanks a lot!
There is a problem though: when i pass incorrect parameters to
such a method, it says, that S has no such field, which is a
misleading error message.
June 22, 2014
There is also a problem: when i declare opDispatch to be private,
i still have access to this forwarding from another package. Is
it a bug or what?
June 22, 2014
On Sun, Jun 22, 2014 at 5:04 PM, monnoroch via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
> There is also a problem: when i declare opDispatch to be private, i still have access to this forwarding from another package. Is it a bug or what?

I don't know. I never used private in conjunction with a template. Let's hope someone more knowledgeable than me can answer this.
June 22, 2014
On Sun, Jun 22, 2014 at 5:02 PM, monnoroch via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
> Thanks a lot!
> There is a problem though: when i pass incorrect parameters to
> such a method, it says, that S has no such field, which is a
> misleading error message.

You can test the mixin with static if, like this:

struct SomeT {
    int foo(double d) { return 0;}
    void bar(double d) { return;}
}

struct S {
  auto opDispatch(string name, Args...)(Args args) {
     static if (is(typeof(mixin("(*iface)." ~ name)(args))))
       return mixin("(*iface)." ~ name)(args);
     else
       pragma(msg, "S." ~ name ~ " cannot be called with arguments of
type " ~ Args.stringof);
    }
    SomeT** iface;
}

void main()
{
  SomeT st;
  SomeT* st_p = &st;
  SomeT** st_p_p = &st_p;
  S s = S(st_p_p);

  s.foo(3.14);
  s.foo("abc");
  s.bar("abc", 3.14);
}
June 22, 2014
Cool! Only this does not show me where the error was. __FILE__
and __LINE__ is not any help here, because it's a template. Any
other way to find out where the actual error was?
June 22, 2014
Nah, this gives me lots of compiler crap, like .empty and others,
when compiler tries to compile them.