www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to create an overwriteable struct that is always const?

reply David Zhang <straivers98 gmail.com> writes:
Say I have a struct `S`:

     struct S {
         /*const*/ char* pointer;
         ... other members ...

         this(/*const*/ char* p, ... others ...) {
             pointer = p;
             ...
         }
     }

What I want, is to be able to use `S` in other data structures 
with the following properties checked by the compiler:

  - The variable can be set
  - The variable can be read
  - The variable cannot be modified, only replaced

Is there a type-safe way to do this? If this were a class, I'd 
try std.typecons.Rebindable.

Thanks
Jun 01 2019
next sibling parent reply drug <drug2004 bk.ru> writes:
01.06.2019 15:51, David Zhang пишет:
 Say I have a struct `S`:
 
      struct S {
          /*const*/ char* pointer;
          ... other members ...
 
          this(/*const*/ char* p, ... others ...) {
              pointer = p;
              ...
          }
      }
 
 What I want, is to be able to use `S` in other data structures with the 
 following properties checked by the compiler:
 
   - The variable can be set
   - The variable can be read
   - The variable cannot be modified, only replaced
 
 Is there a type-safe way to do this? If this were a class, I'd try 
 std.typecons.Rebindable.
 
 Thanks
https://dlang.org/phobos/std_typecons.html#Rebindable ?
Jun 01 2019
parent drug <drug2004 bk.ru> writes:
01.06.2019 15:55, drug пишет:
 Is there a type-safe way to do this? If this were a class, I'd try 
 std.typecons.Rebindable.
Ah, sorry))
Jun 01 2019
prev sibling next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 01.06.19 14:51, David Zhang wrote:
      struct S {
          /*const*/ char* pointer;
          ... other members ...
 
          this(/*const*/ char* p, ... others ...) {
              pointer = p;
              ...
          }
      }
 
 What I want, is to be able to use `S` in other data structures with the 
 following properties checked by the compiler:
 
   - The variable can be set
   - The variable can be read
   - The variable cannot be modified, only replaced
How is setting/replacing different from modifying?
 Is there a type-safe way to do this? If this were a class, I'd try 
 std.typecons.Rebindable.
struct S { const(char)* pointer; /* ... */ }
Jun 01 2019
parent reply David Zhang <straivers98 gmail.com> writes:
On Saturday, 1 June 2019 at 13:00:50 UTC, ag0aep6g wrote:

 How is setting/replacing different from modifying?
e.g.: S s; this() { s = ...; } update(S s) { this.s = s; } mod(int i) { s.i = i; } // illegal Kinda like how strings can be copied and assigned to, but not modified.
Jun 01 2019
parent reply ag0aep6g <anonymous example.com> writes:
On 02.06.19 04:22, David Zhang wrote:
 On Saturday, 1 June 2019 at 13:00:50 UTC, ag0aep6g wrote:
 
 How is setting/replacing different from modifying?
e.g.:     S s;     this() { s = ...; }     update(S s) { this.s = s; }     mod(int i) { s.i = i; } // illegal Kinda like how strings can be copied and assigned to, but not modified.
The `string` itself can be modified: You can change its length, and you can make it refer to other characters. That's modifying. You can't modify the string's characters, because the string refers to them with an `immutable(char)*` pointer. That means the pointer itself is mutable (can be modified), but the data it points to is immutable (can't be modified). You can do the same in your struct: `const(char)* pointer;`. Then you can modify the pointer but you can't modify the data it points to.
Jun 02 2019
parent David Zhang <straivers98 gmail.com> writes:
Ah, fair enough.
Jun 02 2019
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 1, 2019 6:51:08 AM MDT David Zhang via Digitalmars-d-learn 
wrote:
 Say I have a struct `S`:

      struct S {
          /*const*/ char* pointer;
          ... other members ...

          this(/*const*/ char* p, ... others ...) {
              pointer = p;
              ...
          }
      }

 What I want, is to be able to use `S` in other data structures
 with the following properties checked by the compiler:

   - The variable can be set
   - The variable can be read
   - The variable cannot be modified, only replaced

 Is there a type-safe way to do this? If this were a class, I'd
 try std.typecons.Rebindable.

 Thanks
If any member variable of a struct is const, then you can't modify that member ever, and assignment isn't possible unless you override opAssign so that it overwrites only the mutable members. It's very rare that it makes sense to make any member variables of a struct const or immutable, because then you basically can't use assignment anymore. You could make all of the member variables private and provide no functions that set any of them, then the only way to change any of their values would be to construct a new value of that type and assign it to the variable. If what you really want is const(S)* though, then it would be simplest to just use const(S)*, though that requires allocating. Rebindable only exists, because the language basically conflates a reference to the class object with the class object itself, meaning that you can't make the class object const without making the reference const. - Jonathan M Davis
Jun 01 2019
parent reply David Zhang <straivers98 gmail.com> writes:
On Saturday, 1 June 2019 at 16:30:12 UTC, Jonathan M Davis wrote:
 If any member variable of a struct is const, then you can't 
 modify that member ever, and assignment isn't possible unless 
 you override opAssign so that it overwrites only the mutable 
 members. It's very rare that it makes sense to make any member 
 variables of a struct const or immutable, because then you 
 basically can't use assignment anymore.

 You could make all of the member variables private and provide 
 no functions that set any of them, then the only way to change 
 any of their values would be to construct a new value of that 
 type and assign it to the variable.

 - Jonathan M Davis
Ideally, I'd like for member functions to be checked against modifying s also, not just externally.
Jun 01 2019
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, June 1, 2019 8:23:58 PM MDT David Zhang via Digitalmars-d-learn 
wrote:
 On Saturday, 1 June 2019 at 16:30:12 UTC, Jonathan M Davis wrote:
 If any member variable of a struct is const, then you can't
 modify that member ever, and assignment isn't possible unless
 you override opAssign so that it overwrites only the mutable
 members. It's very rare that it makes sense to make any member
 variables of a struct const or immutable, because then you
 basically can't use assignment anymore.

 You could make all of the member variables private and provide
 no functions that set any of them, then the only way to change
 any of their values would be to construct a new value of that
 type and assign it to the variable.

 - Jonathan M Davis
Ideally, I'd like for member functions to be checked against modifying s also, not just externally.
If the member functions are const or inout, then they won't be able to modify any members. - Jonathan M Davis
Jun 01 2019