Why D const is annoying

Steven Schveighoffer schveiguy at yahoo.com
Sun Dec 11 08:23:18 PST 2011


On Sat, 10 Dec 2011 14:47:15 -0500, Mehrdad <wfunction at hotmail.com> wrote:

> On 12/10/2011 3:33 AM, Walter Bright wrote:
>> On 12/10/2011 3:14 AM, Mehrdad wrote:
>>> ... and another... (yes, this one _IS_ a const issue)
>>>
>>> struct S { int opApply(scope int delegate(ref inout(int)) dg) inout {  
>>> return 0; } }
>>> void main()
>>> {
>>> foreach (i; S()) { }
>>> }
>>>
>>> Error: inout on parameter means inout must be on return type as well  
>>> (if from D1
>>> code, replace with 'ref')
>>
>> Right. inout has no point if it also does not appear on the return type.
>>
>> The purpose of inout is to transfer the 'constness' of the argument to  
>> the return type. If inout isn't on the return type somewhere, there's  
>> likely a design mistake in your code. It's like having:
>>
>> {
>>     a + b;
>> }
>>
>> Which is an error in D because such is pointless.
>
> Oh yeah, I just realized -- I think you missed the _second_ 'inout'.
> It's indeed on a parameter! It's just on the implicit 'this' parameter,  
> not on an explicit one. This is a bug (IMO, arising from the fact that  
> inout() is treated like a type constructor, whereas it shouldn't be).

I'll split it out so it's easier to see:

alias int delegate(ref inout(int)) dgtype;

int opApply(dgtype dg) inout;

Notice that neither dgtype or opapply has inout on the return type.  Hence  
the error.

However, I know what you are trying to do.  You are trying to say that  
"while inside the delegate, use the constancy of the actual type".  It  
won't work, because inout applies as const the *entire time* you are  
inside an inout function.  Even when calling an external delegate.   
opApply is not like a range, it executes the foreach loop entirely inside  
the context of opApply.  That is one advantage of ranges (but it's hard to  
take advantage, since you would currently have to define a range for each  
const type).

AFAIK, the only way to do this properly is to have two different versions,  
one for const, one for non-const.

And yes, inout should be a type constructor.  It has to be, I don't know  
where you got the idea it shouldn't.

-Steve


More information about the Digitalmars-d mailing list