Question

In an object, I have an array of const-handles to some object of another specific class. In a method, I may want to return one of this handles as an inout-parameter. Here as a simplified example:

class A {}

class B {
    const(A) a[];
    this() { 
        a = [new A(), new A(), new A()];
    }

    void assign_const(const(A)* value) const {
        // *value = a[0]; // fails with: Error: cannot modify const expression *value
    }
}
void main() {
    const(A) a;
    B b = new B();
    b.assign_const(&a);
    assert(a == b.a[0]); // fails .. obviously
}

I do not want to remove the const in the original array. Class B is meant as some kind of view onto a collection constant A-items. I'm new to D coming from C++. Do I have messed up with const-correctness in the D-way? I've tried several ways to get this to work but have no clue how to get it right.

How is the correct way to perform this lookup without "evil" casting?

Was it helpful?

Solution

Casting away const and modifying an element is undefined behavior in D. Don't do it. Once something is const, it's const. If the element of an array is const, then it can't be changed. So, if you have const(A)[], then you can append elements to the array (since it's the elements that are const, not the array itself), but you can't alter any of the elements in the array. It's the same with immutable. For instance, string is an alias for immutable(char)[], which is why you can append to a string, but you can't alter any of its elements.

If you want an array of const objects where you can alter the elements in the array, you need another level of indirection. In the case of structs, you could use a pointer:

const(S)*[] arr;

but that won't work with classes, because if C is a class, then C* points to a reference to a class object, not to the object itself. For classes, you need to do

Rebindable!(const C) arr;

Rebindable is in std.typecons.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top