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