www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Compiler generated opAssign

reply Christopher Winter <christopher.winter ahrefs.com> writes:
What does the compiler generated opAssign for a struct look like?

Let's say I have a struct, which has at least one `const` member.

```
struct S
{
     this(int some_a, int some_b)
     {
         a = some_a;
         b = some_b;
     }
     int a;
     const int b;
}
```

If I then try to assign to it, the compiler complains that struct 
instances with const members cannot be be modified.


```
     auto s = S(1, 2);
     s = S(3, 4);
```

Full example here: https://run.dlang.io/is/ssT12m

This makes sense to me if I understand the compiler to be 
generating a member-by-member assignment operator like in C++, 
but the description in Programming in D states that in D 
(Assignment Operator section 
[here](http://ddili.org/ders/d.en/special_functions.html)) the 
compiler generated function will create a temporary copy of the 
right-hand-side, and then replace the left-hand-side with that 
temporary copy. To me that description implies that const members 
should be ok when it comes to assigning to the entire object.

In my specific encounter with this scenario, I'm dealing with 
`core.stdcpp.string_view` so I can't modify the definition to 
remove the const member. Also with an old version of ldc I have 
on my linux machine this seems to work, though I'm not able to 
replicate that with the "all dmd versions" option on run.dlang.io 
(where they all fail to compile).
Sep 01 2023
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, September 1, 2023 6:46:33 PM BST Christopher Winter via 
Digitalmars-d wrote:
 What does the compiler generated opAssign for a struct look like?

 Let's say I have a struct, which has at least one `const` member.

 ```
 struct S
 {
      this(int some_a, int some_b)
      {
          a = some_a;
          b = some_b;
      }
      int a;
      const int b;
 }
 ```

 If I then try to assign to it, the compiler complains that struct
 instances with const members cannot be be modified.


 ```
      auto s = S(1, 2);
      s = S(3, 4);
 ```

 Full example here: https://run.dlang.io/is/ssT12m

 This makes sense to me if I understand the compiler to be
 generating a member-by-member assignment operator like in C++,
 but the description in Programming in D states that in D
 (Assignment Operator section
 [here](http://ddili.org/ders/d.en/special_functions.html)) the
 compiler generated function will create a temporary copy of the
 right-hand-side, and then replace the left-hand-side with that
 temporary copy. To me that description implies that const members
 should be ok when it comes to assigning to the entire object.

 In my specific encounter with this scenario, I'm dealing with
 `core.stdcpp.string_view` so I can't modify the definition to
 remove the const member. Also with an old version of ldc I have
 on my linux machine this seems to work, though I'm not able to
 replicate that with the "all dmd versions" option on run.dlang.io
 (where they all fail to compile).
It doesn't matter whether the members are assigned to individually or if a mutated copy is blitted onto the original. Either would involve mutating const which would violate the type system. Unlike C++, D's const actually means const and does not have backdoors. If any version of any D compiler allows you to ever mutate const, it's a bug. And casting away const to mutate an object is undefined behavior, because it violates the type system. Const objects can only be modified via mutable references/pointers pointing to the same object, which wouldn't be legal with value types like int, and obtaining such a mutable reference with any type cannot be done via casting without violating the type system. So, in general, having const or immutable member variables in a struct is a terrible idea in D precisely because it's not legal to assign to them. I can't speak to what's being done with core.stdcpp.string_view, because I've never used it, but if you're dealing with a type that you do not control and thus cannot avoid having a const or immutable member, then it's simply not going to be legal to assign to any variable of that type. - Jonathan M Davis
Sep 01 2023