January 07, 2015 Re: const Propagation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 29 December 2014 at 20:24:13 UTC, Steven Schveighoffer wrote:
> On 12/29/14 3:11 PM, Steven Schveighoffer wrote:
>> 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.
>
> OK, it's not inferring the const on 'this'. It ONLY does this if you have a 'this' template parameter in the template list. This works:
>
> void blah(T, this _)(void function(T t) f)
>
> interesting, can someone explain this requirement?
>
> -Steve
I'd really like to know that, too ;-). Thank you again for all your answers!
| |||
January 08, 2015 Re: const Propagation | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Julian Kranz | On 1/7/15 1:27 PM, Julian Kranz wrote: > On Monday, 29 December 2014 at 20:24:13 UTC, Steven Schveighoffer wrote: >> OK, it's not inferring the const on 'this'. It ONLY does this if you >> have a 'this' template parameter in the template list. This works: >> >> void blah(T, this _)(void function(T t) f) >> >> interesting, can someone explain this requirement? >> > > I'd really like to know that, too ;-). Thank you again for all your > answers! Yeah, I think this is a missed opportunity. 1. A template is (most of the time) automatically not virtual. 2. If a template can be inferred const or inout, it can be called with more instances for free. 3. In some cases, when the template parameters itself may determine the ability of the function to be const or not, it's not possible to slap a "const" on there, or split it up. I notice there are already a couple of reports about this: https://issues.dlang.org/show_bug.cgi?id=7521 https://issues.dlang.org/show_bug.cgi?id=8407 -Stev | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply