On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:
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?

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.

Reply via email to