Thread overview
inout, delegates, and visitor functions.
Oct 24, 2015
Sebastien Alaiwan
Oct 24, 2015
ponce
Oct 24, 2015
Sebastien Alaiwan
Oct 24, 2015
ponce
October 24, 2015
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!

October 24, 2015
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.

October 24, 2015
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.


October 24, 2015
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.