digitalmars.D.learn - Cannot implicitly convert expression of type const(string[]) to
- Andrey (7/30) Jan 08 2021 I want to pass variable "row" inside function "test" as a read
- kdevel (3/4) Jan 08 2021 Drop the "const" before "ref".
- tsbockman (33/63) Jan 08 2021 Your code has a logical inconsistency which the compiler has
- tsbockman (5/8) Jan 08 2021 Oops, that should say:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (10/35) Jan 08 2021 The destination is immutable(char)[]. The characters cannot be changed.
- Paul Backus (6/27) Jan 08 2021 Remember, `string[]` means `immutable(char)[][]`, so there are
- tsbockman (32/39) Jan 08 2021 No, it's not. string[] means immutable(char)[][] - note the
Hello,struct Value { int value; string data; string[] text; } void test(const ref Value value) { Value other = void; other.text = value.text; } void main() { Value row; row.value = 10; row.data = "ttttggg"; test(row); }I want to pass variable "row" inside function "test" as a read only parameter. Inside I create another variable and try to assign field "text". On that line I get:Error: cannot implicitly convert expression value.text of type const(string[]) to string[].1. How to assign correctly (and without dup/ugly cast())? 2. Or how to pass "row" correctly?
Jan 08 2021
On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote: [...]2. Or how to pass "row" correctly?Drop the "const" before "ref".
Jan 08 2021
On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:Hello,Your code has a logical inconsistency which the compiler has rightly detected and flagged for you. You should actually fix the inconsistency, not just shut the compiler up. If the compiler accepted your code, it would be possible to later modify the array pointed at by `row.text` through `other.text`, because `other.text` is not `const`. This would violate your stated desire to pass `row` as read-only. There are various ways you can fix this, depending on your needs: 1) Change the type of `other` to `const(Value)` so that `other.text` cannot be used to modify `row.text`. 2) Change the type of `Value.text` to `const(string[])` so that it cannot be used to modify `row.text`. 3) Assign a copy (`dup`) of `row.text` to `other.text` instead, so that mutating the array pointed to by `other.text` will not modify the original read-only `row`. 4) Implement a copy-on-write scheme for `Value.text`. 5) Tell the compiler that `other.text` may be used to mutate `row.text` by `const` from the `value` parameter of `test`. Do not do this unless that's really what you want! (1) and (2) are good options, if their limitations happen to fit whatever you're really doing. (Note that either requires you to write a constructor for `Value` since you won't be able to directly write to `Value.text` anymore.) Unless you are managing huge quantities of data with this `Value` type, (3) is a perfectly reasonable thing to do and you shouldn't feel guilty about the small "waste" of memory and CPU time for the extra allocation. (4) is an option of last resort - not a crazy one, but not worth the trouble if the amount of data is small relative to system resources and/or the other activities of the program. (5) is simple but WRONG unless you are trying to create multiple references to the same mutable data.struct Value { int value; string data; string[] text; } void test(const ref Value value) { Value other = void; other.text = value.text; } void main() { Value row; row.value = 10; row.data = "ttttggg"; test(row); }I want to pass variable "row" inside function "test" as a read only parameter. Inside I create another variable and try to assign field "text". On that line I get:Error: cannot implicitly convert expression value.text of type const(string[]) to string[].1. How to assign correctly (and without dup/ugly cast())? 2. Or how to pass "row" correctly?
Jan 08 2021
On Friday, 8 January 2021 at 23:10:13 UTC, tsbockman wrote:5) Tell the compiler that `other.text` may be used to mutate `row.text` by `const` from the `value` parameter of `test`. Do not do this unless that's really what you want!Oops, that should say: 5) Tell the compiler that `other.text` may be used to mutate `row.text` by *removing* `const` from the `value` parameter of `test`. Do not do this unless that's really what you want!
Jan 08 2021
On 1/8/21 3:10 PM, tsbockman wrote:On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:The destination is immutable(char)[]. The characters cannot be changed. We can still append but other slices that share the same data is protected by D's no-stomp decision.Hello,struct Value { int value; string data; string[] text;Even though the source is 'const ref', other.text is a copy of the slice object (the pointer and the length). Because the elements are immutable, other.text cannot mutate value.text.} void test(const ref Value value) { Value other = void; other.text = value.text;} void main() { Value row; row.value = 10; row.data = "ttttggg"; test(row); }Your code has a logical inconsistencyI don't see where. I think this is one of those too strict cases of D where I unhappily slap a cast and move on. Ali
Jan 08 2021
On Saturday, 9 January 2021 at 02:07:50 UTC, Ali Çehreli wrote:On 1/8/21 3:10 PM, tsbockman wrote:Remember, `string[]` means `immutable(char)[][]`, so there are actually two layers of pointer + length here. The outer one is copied, but the inner one is not, which means that mutating `other.text[0]` would also mutate `value.text[0]` if this assignment were allowed.On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:The destination is immutable(char)[]. The characters cannot be changed. We can still append but other slices that share the same data is protected by D's no-stomp decision.Hello,struct Value { int value; string data; string[] text;Even though the source is 'const ref', other.text is a copy of the slice object (the pointer and the length). Because the elements are immutable, other.text cannot mutate value.text.} void test(const ref Value value) { Value other = void; other.text = value.text;
Jan 08 2021
On Saturday, 9 January 2021 at 02:07:50 UTC, Ali Çehreli wrote:The destination is immutable(char)[].No, it's not. string[] means immutable(char)[][] - note the second set of brackets.Even though the source is 'const ref', other.text is a copy of the slice object (the pointer and the length). Because the elements are immutable, other.text cannot mutate value.text.The elements are not immutable. Each element is an mutable slice of immutable characters.The cast you propose breaks the type system. For example: module app; import std.stdio; struct Value { int value; string data; string[] text; } void test(const ref Value value) trusted // Don't do this! { Value other = void; other.text = cast(string[]) value.text; // This cast is system for good reason. other.text[0] = "Oops"; } void main() safe { immutable(Value) row = { value: 10, data: "ttttggg", text: [ "Don't change me, bro!" ] }; writeln(row.text); test(row); writeln(row.text); }Your code has a logical inconsistencyI don't see where. I think this is one of those too strict cases of D where I unhappily slap a cast and move on.
Jan 08 2021