December 29, 2014
No, actually I don't at all understand why the function does not need to be const any longer since this code does not compile:

import std.stdio;

class Hugo {
  public int x = 42;

  void blah(this T)(void function(const Hugo h) f) {
    f(this);
  }
}

void main() {
    Hugo hugo = new Hugo();

    const Hugo inge = hugo;
    void function(const Hugo h) g = function(const Hugo h) {
      write("foobar ");
      writeln(h.x);
    };
    inge.blah(g);
}

Sorry guys, I know I'm a bloody D beginner, ...
December 29, 2014
Sorry, copy+paste error, I of course meant the following :-/...

import std.stdio;

class Hugo {
  public int x = 42;

  void blah(void function(const Hugo h) f) {
    f(this);
  }
}

void main() {
    Hugo hugo = new Hugo();

    const Hugo inge = hugo;
    void function(const Hugo h) g = function(const Hugo h) {
      write("foobar ");
      writeln(h.x);
    };
    inge.blah(g);
}
December 29, 2014
On 12/29/14 10:36 AM, Julian Kranz wrote:
> On Monday, 29 December 2014 at 15:25:13 UTC, Daniel Kozak wrote:
>> On Monday, 29 December 2014 at 15:17:30 UTC, Julian Kranz wrote:
>>> Thank you for your answers. All of your suggestions go into the right
>>> direction, however there's still one thing left that breakes it: the
>>> method itself (blah()) needs to be marked as const to be callable on
>>> a const object. Therefore, I need something like
>>>
>>> void blah(...)(...) if(this ia const object) const : nothing {
>>> }

Not in my solution, because blah is not a "method". T will become const if the callee is const. As I said, you may have to do T : const(Hugo).

>>>
>>
>> Did you try my solutions? It doesn`t need blah to be const
>
> Uuuhm, you're right, it works :-D I don't completely understand why the
> compiler does not require the function to be sonst any longer...

I think Daniel's solution would work if the compiler infers const. I'm not sure that it does, but if it works, it does :)

The compiler can infer attributes if a function is a template. Not all attributes, but some of them.

-Steve
December 29, 2014
On Monday, 29 December 2014 at 15:53:25 UTC, Steven Schveighoffer wrote:
> The compiler can infer attributes if a function is a template. Not all attributes, but some of them.
>
> -Steve

Ah, thanks, this explains it ;-). However, it's kind of uncool that this only works for templates...
December 29, 2014
On Monday, 29 December 2014 at 16:03:41 UTC, Julian Kranz wrote:
> On Monday, 29 December 2014 at 15:53:25 UTC, Steven Schveighoffer wrote:
>> The compiler can infer attributes if a function is a template. Not all attributes, but some of them.
>>
>> -Steve
>
> Ah, thanks, this explains it ;-). However, it's kind of uncool that this only works for templates...

If you wish to dig into the details, there's a free ebook with a good explanation here:
http://ddili.org/ders/d.en/index.html

Search for "this template parameters for member functions" in
http://ddili.org/ders/d.en/templates_more.html
December 29, 2014
On Monday, 29 December 2014 at 16:03:41 UTC, Julian Kranz wrote:
> On Monday, 29 December 2014 at 15:53:25 UTC, Steven Schveighoffer wrote:
>> The compiler can infer attributes if a function is a template. Not all attributes, but some of them.
>>
>> -Steve
>
> Ah, thanks, this explains it ;-). However, it's kind of uncool that this only works for templates...

I've gotten into the habit of templating every function, even if its a zero-parameter template, because trying to manage all the pure/safe/const/nothrow annotations myself always winds up putting me in a corner once the code starts to grow. It's not so bad, really, one advantage is that you can define functions that may or may not compile, but will only trigger an error if they are called on a type that doesn't support it. You can issue compile time branches using "static if (is (typeof(function_name)))" to gain an extra degree of control over this process.
December 29, 2014
On Monday, 29 December 2014 at 16:09:33 UTC, Daniel N wrote:
> On Monday, 29 December 2014 at 16:03:41 UTC, Julian Kranz wrote:
>> On Monday, 29 December 2014 at 15:53:25 UTC, Steven Schveighoffer wrote:
>>> The compiler can infer attributes if a function is a template. Not all attributes, but some of them.
>>>
>>> -Steve
>>
>> Ah, thanks, this explains it ;-). However, it's kind of uncool that this only works for templates...
>
> If you wish to dig into the details, there's a free ebook with a good explanation here:
> http://ddili.org/ders/d.en/index.html
>
> Search for "this template parameters for member functions" in
> http://ddili.org/ders/d.en/templates_more.html

Thank you, I should do that :-) Actually, I've read "The D Programming Language" so time ago...
December 29, 2014
On Monday, 29 December 2014 at 16:13:03 UTC, Vlad Levenfeld wrote:
> On Monday, 29 December 2014 at 16:03:41 UTC, Julian Kranz wrote:
>> On Monday, 29 December 2014 at 15:53:25 UTC, Steven Schveighoffer wrote:
>>> The compiler can infer attributes if a function is a template. Not all attributes, but some of them.
>>>
>>> -Steve
>>
>> Ah, thanks, this explains it ;-). However, it's kind of uncool that this only works for templates...
>
> I've gotten into the habit of templating every function, even if its a zero-parameter template, because trying to manage all the pure/safe/const/nothrow annotations myself always winds up putting me in a corner once the code starts to grow. It's not so bad, really, one advantage is that you can define functions that may or may not compile, but will only trigger an error if they are called on a type that doesn't support it. You can issue compile time branches using "static if (is (typeof(function_name)))" to gain an extra degree of control over this process.

Is that really cool? I mean, is wise to have the compiler treat templates and non-templates differently? C++ has tons of such inconsistencies which is the main reason I don't really like C++...
December 29, 2014
On Monday, 29 December 2014 at 14:13:20 UTC, Daniel Kozak wrote:
> On Monday, 29 December 2014 at 13:22:41 UTC, Julian Kranz wrote:
>> So I hope you understand; I've got no problem with changing the type of the function g as you supposed. The bad thing is the additional overload that results in duplicated code.
>
> So you can write something like this:
>
> import std.stdio;
>
> class Hugo {
>      public int x = 42;
>
>      void blah(this T)(void function(T h) f)
>      {
>          f(this);
>      }
> }
>
> void main() {
>      Hugo hugo = new Hugo();
>      void function(Hugo h) f = function(Hugo h) {
>          h.x = 99;
>      };
>      hugo.blah(f);
>
>      const Hugo inge = hugo;
>      void function(const Hugo h) g = function(const Hugo h) {
>          writeln("foobar");
>      };
>      inge.blah(g);
> }

So template methods deduce const now? Sweet.

I see one wart on this: `inge.blah((h) {});` doesn't work.
December 29, 2014
On Monday, 29 December 2014 at 13:20:39 UTC, Julian Kranz wrote:
> Thank you for your answer. This kind of thing also works for C++, but that would mean that I would implement the whole visitor twice - one const and one non-const version. Is that really the only way? Can't I tell the D compiler that "the argument of that lambda shares the const-ness of the current object"?
>
> D offers "inout"; this actually aims into the right directing, but I guess it does not help here.
>
> Is there any "static if"-something construct to check the const-ness of an object?

There's a pattern I suggested before[1] that I'd like to mention
in addition to the template solutions Steven Schveighoffer and
Daniel Kozak gave:

Call the non-const overload from the const overload and cast
accordingly.

In your case:

   void blah(void function(Hugo h) f) {
     f(this);
   }
   void blah(void function(const Hugo h) f) const {
     (cast(Hugo) this).blah(cast(void function(Hugo)) f);
   }

This is safe as long as the non-const overload does not mutate
the object when f doesn't. BUT you have to make sure of that
yourself; the compiler can't help anymore.

[1]
http://stackoverflow.com/questions/22442031/how-to-make-a-template-function-const-if-the-template-is-true/22442425#22442425