Thread overview
opDispatch() is pretty damn great
Jan 08, 2014
Szymon Gatner
Jan 08, 2014
Adam D. Ruppe
Jan 08, 2014
Szymon Gatner
Jan 08, 2014
Brad Anderson
Jan 09, 2014
Szymon Gatner
Jan 08, 2014
bearophile
Jan 09, 2014
Szymon Gatner
Jan 09, 2014
Jakob Ovrum
January 08, 2014
Still exploring what D has to offer but this blew my mind:

import std.stdio;

struct Base
{
  void print(string text)
  {
    writeln("Base : " ~ text);
  }
  int add(int a, int b)
  {
    return a + b;
  }
}

struct Wrap
{
  auto opDispatch(string op, Args...)(Args args)
  {
    enum name = op;
    return __traits(getMember, base, name)(args);
  }
  Base base;
}

int main(string[] argv)
{
  Wrap wrap;
  wrap.print("wrapped call, magic!");
  auto res = wrap.add(1, 5);
  return 0;
}

I don't quite understand why "enum name" part is necessary (as my understanding is that "op" is compile-time constant anyway) but since I am crap at D that is what worked for me. I was thinking for log time how great something like that would be in C++ and I just tried this id D... Mind blown... std::reference_wrapper<> would be a zillion times more usable with equivalent of opDispatch() this powerful.
January 08, 2014
On Wednesday, 8 January 2014 at 23:20:06 UTC, Szymon Gatner wrote:
> I don't quite understand why "enum name" part is necessary

It isn't!
January 08, 2014
On Wednesday, 8 January 2014 at 23:20:06 UTC, Szymon Gatner wrote:
> Still exploring what D has to offer but this blew my mind:
>
> <snip>
>
> I don't quite understand why "enum name" part is necessary (as my understanding is that "op" is compile-time constant anyway) but since I am crap at D that is what worked for me. I was thinking for log time how great something like that would be in C++ and I just tried this id D... Mind blown... std::reference_wrapper<> would be a zillion times more usable with equivalent of opDispatch() this powerful.

There is also `alias this` for subtyping.

	import std.stdio;
	
	struct Base
	{
	  void print(string text)
	  {
		writeln("Base : " ~ text);
	  }
	  int add(int a, int b)
	  {
		return a + b;
	  }
	}
	
	struct Wrap
	{
	  Base base;
	  alias base this;
	}
	
	void baseOnly(Base b)
	{
		b.print("passed in a Wrap!");
	}
	
	int main(string[] argv)
	{
	  Wrap wrap;
	  wrap.print("wrapped call, magic!");
	  baseOnly(wrap);
	  auto res = wrap.add(1, 5);
	  return 0;
	}
January 08, 2014
Szymon Gatner:

Two small improvements in your code:

>     writeln("Base : " ~ text);

=>

     writeln("Base : ", text);


> int main(string[] argv)
> {
> ...
>   return 0;
> }

=>

> void main(string[] argv)
> {
> ...
> }

Or even:

> void main()
> {
> ...
> }

Bye,
bearophile
January 08, 2014
On Wednesday, 8 January 2014 at 23:26:26 UTC, Adam D. Ruppe wrote:
> On Wednesday, 8 January 2014 at 23:20:06 UTC, Szymon Gatner wrote:
>> I don't quite understand why "enum name" part is necessary
>
> It isn't!

Indeed, I don't know why it didn't compile for me the first time.
January 09, 2014
On Wednesday, 8 January 2014 at 23:27:37 UTC, Brad Anderson wrote:
> On Wednesday, 8 January 2014 at 23:20:06 UTC, Szymon Gatner wrote:
>> Still exploring what D has to offer but this blew my mind:
>>
>> <snip>
>>
>> I don't quite understand why "enum name" part is necessary (as my understanding is that "op" is compile-time constant anyway) but since I am crap at D that is what worked for me. I was thinking for log time how great something like that would be in C++ and I just tried this id D... Mind blown... std::reference_wrapper<> would be a zillion times more usable with equivalent of opDispatch() this powerful.
>
> There is also `alias this` for subtyping.
>
> 	import std.stdio;
> 	
> 	struct Base
> 	{
> 	  void print(string text)
> 	  {
> 		writeln("Base : " ~ text);
> 	  }
> 	  int add(int a, int b)
> 	  {
> 		return a + b;
> 	  }
> 	}
> 	
> 	struct Wrap
> 	{
> 	  Base base;
> 	  alias base this;
> 	}
> 	
> 	void baseOnly(Base b)
> 	{
> 		b.print("passed in a Wrap!");
> 	}
> 	
> 	int main(string[] argv)
> 	{
> 	  Wrap wrap;
> 	  wrap.print("wrapped call, magic!");
> 	  baseOnly(wrap);
> 	  auto res = wrap.add(1, 5);
> 	  return 0;
> 	}

I was actually thinking about subtyping too but I don't know how to do alias this with opDispatch() call forwarding to Base from Wrap

January 09, 2014
On Wednesday, 8 January 2014 at 23:46:28 UTC, bearophile wrote:
> Szymon Gatner:
>
> Two small improvements in your code:
>
>>    writeln("Base : " ~ text);
>
> =>
>
>      writeln("Base : ", text);
>
>
>> int main(string[] argv)
>> {
>> ...
>>  return 0;
>> }
>
> =>
>
>> void main(string[] argv)
>> {
>> ...
>> }
>
> Or even:
>
>> void main()
>> {
>> ...
>> }
>
> Bye,
> bearophile

Thanks, was not aware, main() was actually generated by VisualD
January 09, 2014
On Thursday, 9 January 2014 at 00:02:00 UTC, Szymon Gatner wrote:
> On Wednesday, 8 January 2014 at 23:46:28 UTC, bearophile wrote:
>> Or even:
>>
>>> void main()
>>> {
>>> ...
>>> }
>>
>> Bye,
>> bearophile
>
> Thanks, was not aware, main() was actually generated by VisualD

Yeah, VisualD was guilty of propagating that poor template for a long time. It's now fixed.

http://d.puremagic.com/issues/show_bug.cgi?id=11277