Struct copy constructor with inout

Paul Backus snarwin at gmail.com
Tue Nov 14 14:58:21 UTC 2023


On Tuesday, 14 November 2023 at 14:36:57 UTC, dhs wrote:
> Just to clarify some more: isn't "s1 = ss1" similar to 
> something like:
>
> ```d
>     const(S1) s1;
>     S1 ss1; // ss1 is now S1.init
>     S1_copy_construct_const_in_const_out(ss1, s1);
> ```
>
> If this is the case, the compile error is expected, but 
> why/how/where do "implicit qualifer conversions" apply here?

The real answer is that constructors are special, and constructor 
calls follow different type-checking rules from normal function 
calls.

Here's an example:

```d
struct S
{
     int n;
     this(int n) const { this.n = n; }
     void fun() const {}
}

void main()
{
     S s;
     s.__ctor(123); // error
     s.fun(); // ok
}

```

Normally, it's fine to call a `const` method on a mutable object, 
because mutable implicitly converts to `const`. But when that 
method is a constructor, it's not allowed.

Why? Because constructors have a special "superpower" that no 
other functions in D have: they're allowed to write to `const` 
and `immutable` variables. This is documented in the spec under 
["Field initialization inside a constructor"][1].

If you could call a `const` constructor on a mutable object, it 
would be possible to use that constructor to violate the type 
system by storing a pointer to `immutable` data in a mutable 
field:

```d
struct S2
{
     int* p;
     this(const int* p) const
     {
         // Ok - counts as initialization
         this.p = p;
     }
}

immutable int answer = 42;

void main()
{
     S2 s2;
     // If this were allowed to compile...
     s2.__ctor(&answer);
     // ...then this could happen
     *s2.p = 12345;
}
```

[1]: https://dlang.org/spec/struct.html#field-init


More information about the Digitalmars-d-learn mailing list