2013-02-12 5 views
4

В объекте у меня есть массив const-handle для некоторого объекта другого определенного класса. В методе я могу вернуть одну из этих ручек в качестве параметра inout. Здесь в качестве упрощенного примера:inout-parameter - заменить один const-handle на другой

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 
} 

Я не хочу удалять const в исходном массиве. Класс B понимается как некоторый вид на постоянную коллекции A. Я новичок в D, идущем с C++. Я перепутался с const-correctness в D-way? Я пробовал несколько способов заставить это работать, но не знаю, как правильно это сделать.

Каков правильный способ выполнения этого поиска без «злого» литья?

ответ

5

Отбрасывание const и изменение элемента является неопределенным поведением в D. Не делайте этого. Когда-то что-то const, это const. Если элемент массива равен const, его нельзя изменить. Итак, если у вас есть const(A)[], вы можете добавлять элементы к массиву (поскольку это элементы, которые являются const, а не самим массивом), но вы не можете изменить ни один из элементов в массиве. То же самое с immutable. Например, string является псевдонимом для immutable(char)[], поэтому вы можете добавить к string, но вы не можете изменить ни один из его элементов.

Если вам нужен массив объектов const, где вы можете изменять элементы в массиве, вам нужен еще один уровень косвенности. В случае структур, вы можете использовать указатель:

const(S)*[] arr; 

, но это не будет работать с классами, потому что если C класс, то C* указывает на ссылку на объект класса, а не к объекту сам. Для классов, вам нужно сделать

Rebindable!(const C) arr; 

Rebindable в std.typecons.

+0

Отказ от const был моим последним вариантом, даже если это было определено поведением. До этого я полностью удалил const. Но это были бы век, прежде чем я нашел приемлемое решение с «Rebindable» (.. или по крайней мере днями). Спасибо! –

+1

Это то, о чем вы, вероятно, узнаете только, если вы прочтете статью, в которой упоминается это или ответ на такой вопрос. Но из-за того, как работает система типа D, вы в значительной степени должны иметь что-то вроде 'Rebindable', чтобы создать класс' const', но не иметь ссылку на 'const' - система типов просто не имеет понятия о различии между двумя. 'Rebindable' решает проблему достаточно хорошо, но поскольку большинство людей не понимают, почему они не могут сделать это на самом языке, это не то, о чем большинство людей подумают. –