www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opDispatch() is pretty damn great

reply "Szymon Gatner" <noemail gmail.com> writes:
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.
Jan 08 2014
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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!
Jan 08 2014
parent "Szymon Gatner" <noemail gmail.com> writes:
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.
Jan 08 2014
prev sibling next sibling parent reply "Brad Anderson" <eco gnuk.net> writes:
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; }
Jan 08 2014
parent "Szymon Gatner" <noemail gmail.com> writes:
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
Jan 08 2014
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Jan 08 2014
parent reply "Szymon Gatner" <noemail gmail.com> writes:
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
Jan 08 2014
parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
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
Jan 08 2014