Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot append constant (struct) type to array

In one struct, Shape I have a function:

...
import graphics.line;

struct Shape {
    Line[] lines;

    void addLine(Line l) {
        lines ~= l;
    }
}

Line is also a struct, but when I put "in Line l" as the argument declaration for addLine(), the compiler bugs out with:

shape.d(12): Error: cannot append type const(Line) to type Line[]

The weird thing is I have a similar piece of code in another module, and it works... So my question is, why is the compiler not happy with it in this case?

like image 918
lmartinking Avatar asked Feb 16 '11 04:02

lmartinking


1 Answers

Basically, whether this works depends on what members your struct has. The in storage class is equivalent to const scope. So, writing void addLine(in Line l) means that l is const. And since const is transitive, all Line l struct members are const, too.

The Shape member Line[] lines is however not const. So, you are trying to append a const Line l to something that is not const. Whether this is possible depends on the types of all members of the struct Line l. If all members of line have value (copy) semantics, this appending (which is an assignment) is possible. If any one member has (some) reference semantics (e.g. a pointer gets copied), this appending is no longer possible. Otherwise, you could give a const Line lc into addLines, but would get a non-const member of lines. Through this, you could change the value with reference semantics, changing the value of the original lc indirectly, too, thereby violating the const guarantee, namely the transitivity of const in D.

Example:

class C { }

struct Line {
    int i;
    // int* p;               // if you uncomment this, addLine fails
    // C c;                  // if you uncomment this, addLine fails
}

struct Shape { 
    Line[] lines;
    void addLine(in Line l) { lines ~= l; }
}

void main() { }

Edit: BTW, another way to make it work is to change Line[] lines; to const(Line)[] lines;. Than the array contains only const elements, and the appending of a const l in addLine is possible.

like image 158
stephan Avatar answered Sep 19 '22 14:09

stephan