const Propagation

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Mon Dec 29 12:11:28 PST 2014


On 12/29/14 2:07 PM, anonymous wrote:
> 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);
>     }

The problem here is, you lose your compiler checks. It's not so much 
that "I know at this moment, mutable blah does not change anything", 
it's "I know at this moment, and anytime in the future, mutable blah 
does not change anything".

Hm... I did think of another solution, using delegates:

private void blahImpl(scope void delegate() f) const {
    ... // do things that don't change this
    f();
    ... // do things that don't change this
}

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

And this time, I did test it, because I was curious enough :)

While you still need the boilerplate of repeating blah for const and 
others, you don't need to repeat the larger implementation. One thing 
you could do is make blah a template which takes Hugo as a template 
type, and then any function that accepts a Hugo (including a base class) 
would be usable, and it then allows you to avoid repetition:

void blah(T)(void function(T t) f) {
    blahImpl((){f(this);});
}

except... drat, it doesn't compile, can't deduce T when it's const(Hugo) 
(that doesn't make much sense). I'll look and see if there is an open 
bug report.

-Steve


More information about the Digitalmars-d mailing list