www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - inout, delegates, and visitor functions.

reply Sebastien Alaiwan <ace17 free.fr> writes:
Hi all,

I'm trying to get the following code to work.
(This code is a simplified version of some algebraic type).
Is it possible to only declare one version of the 'apply' 
function?
Or should I declare the const version and the non-const version?

I tried using "inout", but I got the following error:

test.d(28): Error: inout method test.E.apply is not callable 
using a mutable object


class E
{
   void apply(void delegate(inout(E) e) f) inout
   {
     f(this);
   }

   int val;
}

void m()
{
   void setToZero(E e)
   {
     e.val = 0;
   }

   void printValue(const E e)
   {
     import std.stdio;
     writefln("Value: %s", e.val);
   }

   E obj;

   obj.apply(&setToZero);
   obj.apply(&printValue);
}

Thanks!
Oct 24 2015
parent reply ponce <contact gam3sfrommars.fr> writes:
On Saturday, 24 October 2015 at 08:51:58 UTC, Sebastien Alaiwan 
wrote:
 Hi all,

 I'm trying to get the following code to work.
 (This code is a simplified version of some algebraic type).
 Is it possible to only declare one version of the 'apply' 
 function?
 Or should I declare the const version and the non-const version?

 I tried using "inout", but I got the following error:

 test.d(28): Error: inout method test.E.apply is not callable 
 using a mutable object


 class E
 {
   void apply(void delegate(inout(E) e) f) inout
   {
     f(this);
   }

   int val;
 }

 void m()
 {
   void setToZero(E e)
   {
     e.val = 0;
   }

   void printValue(const E e)
   {
     import std.stdio;
     writefln("Value: %s", e.val);
   }

   E obj;

   obj.apply(&setToZero);
   obj.apply(&printValue);
 }

 Thanks!
Hi Sebastien, That was an interesting question and I didn't succeed with 'inout' either without duplicating apply. I have a partial solution here: http://dpaste.dzfl.pl/b5ec7f16b912 which templatizes the delegate type, but is probably not what you want. The qualifier is not carried on to the apply() function. When taking a const delegate it will still not be const.
Oct 24 2015
parent reply Sebastien Alaiwan <ace17 free.fr> writes:
Hi ponce,
Thanks for your suggestion.
I think I may have found the beginning of a solution:

class E
{
   import std.traits;

   void apply(this F, U)(void delegate(U e) f)
     if(is(Unqual!U == E))
   {
     f(this);
   }

   int val;
}

int main()
{
   void setToZero(E e)
   {
     e.val = 0;
   }

   void printValue(const E e)
   {
     import std.stdio;
     writefln("Value: %s", e.val);
   }

   E obj;

   obj.apply(&setToZero);
   obj.apply(&printValue);

   const(E) objConst;
   //objConst.apply(&setToZero);
   objConst.apply(&printValue);

   return 0;
}


Basically, I avoid the 'const'/'inout' attribute of the 'apply' 
function by using a 'this F' template argument.
Then, I need a second template argument 'U', otherwise, I can't 
call 'printValue' on a non-const E instance.
Oct 24 2015
parent ponce <contact gam3sfrommars.fr> writes:
On Saturday, 24 October 2015 at 11:28:17 UTC, Sebastien Alaiwan 
wrote:
 Hi ponce,
 Thanks for your suggestion.
 I think I may have found the beginning of a solution:

 class E
 {
   import std.traits;

   void apply(this F, U)(void delegate(U e) f)
     if(is(Unqual!U == E))
   {
     f(this);
   }

   int val;
 }

 int main()
 {
   void setToZero(E e)
   {
     e.val = 0;
   }

   void printValue(const E e)
   {
     import std.stdio;
     writefln("Value: %s", e.val);
   }

   E obj;

   obj.apply(&setToZero);
   obj.apply(&printValue);

   const(E) objConst;
   //objConst.apply(&setToZero);
   objConst.apply(&printValue);

   return 0;
 }
Clever. It works because of const inference on template functions. Didn't know you could use 'this' as a type.
Oct 24 2015