“Out” parameters and destructors

Salih Dincer salihdb at hotmail.com
Fri Mar 21 04:23:58 UTC 2025


On Saturday, 15 March 2025 at 11:44:14 UTC, Ogi wrote:
> On Friday, 14 March 2025 at 16:54:10 UTC, Ali Çehreli wrote:
>> Although understandably undesirable, this is according to spec:
>>
>>   https://dlang.org/spec/function.html#ref-params
>>
>> "An out parameter [...] is initialized with x.init upon 
>> function invocation."
>
> I want to clarify if this is intentional or not, and what is 
> the intention if it is. Currently, it turns out that the 
> variable has to be destroyed before passing it as an “out” 
> argument. It’s counter-intuitive, and it defeats the purpose of 
> “out” parameters.
>

I think you're exaggerating the issue more than it is! Who is 
going to use a local variable in their code? Let's look at the 
issue like this:

```d
enum check = 40;
struct S
{
     int num = check;
     auto inc2() => num += 2;
}

void foo(out S s)
in (s.num == check)
{
     assert(s.num == check);
}


import std.stdio;
void main()
{
     S s;
     s.foo();

     s.inc2();
     s.num.writeln; // 42
     
     void bar(out S s)
     in (s.num == check)
     {
         assert(s.num == check);
     }

     bar(s);
     s.num.writeln; // 40
}
```

The issue arises in the bar(s); call. Although s.num was 
incremented to 42 before bar(s), the out parameter in D resets s 
to its default state before entering bar(). Since s.num is 
initialized to check (which is 40), the assertion inside bar() 
holds, and after the function call, s.num is reset to 40. This 
explains why s.num.writeln; prints 40 after bar(s), effectively 
discarding the previous increment.

SDB at 79


More information about the Digitalmars-d mailing list