2016-05-28 2 views
1

У меня есть следующий код в D:Как вернуть возвращаемые ссылочные типы без разрыва?

import std.stdio; 
import std.container.array; 

class RefType { } 

class MyContainer { 
    private Array!RefType test; 
    RefType result() const { // I want const on this, not on return type 
     return test[0];  // use opIndex() from Array(T) 
     // Error: cannot implicitly convert expression (this.test.opIndex(0u)) 
     // of type const(RefType) to main.RefType 
    } 
} 

int main(string[] argv) { 
    auto c = new MyContainer; auto r = c.result(); return 0; 
} 

Как вы можете видеть, что я хочу, чтобы вернуть ссылочный тип из пользовательского класса контейнера. Но opIndex() из массива не дает разрешения на это, почему?

Я думаю, что opIndex() должен возвращать RefType вместо значения const(RefType) потому, что массив является Array!RefType.

Это ошибка? или намерение проекта? Если это намеренный дизайн, как я могу получить то, что хочу?

+0

попробуйте заменить 'const'' inout'.поэтому 'inout (RefType) result() inout {return test [0]; } 'и посмотреть, работает ли это для вас –

+0

Да, это работает! но в чем смысл ключевого слова inout? –

+0

Я тестировал и не нарушал константу :), пожалуйста, заполните ее как ответ. Это просто я нашел. –

ответ

0

Я думаю, что opIndex() должен возвращать переменный тип RefType вместо значения по Const (переменный типа RefType), так как массив является массив! Переменным типа RefType.

Нет, это неправильно. Когда вы определяете свой memthod как const, вы также указали, что все члены класса также являются константами. Это означает, что независимо от того, какой тип член имеет в определении, внутри вашего метода result они (как минимум) const. Таким образом, компилятор полностью оправдывает возврат возвращаемой ошибки.

Обычный (например C++) способ решения этой проблемы заключается в определении двух (или, D, три) Перегрузки:

RefType result() { 
    return test[0]; 
} 
RefType result() const { 
    return test[0]; 
} 
RefType result() immutable { 
    return test[0]; 
} 

Так, один для случая класс является изменяемым, который возвращает изменяемый Справка. Один для случая: класс const, который возвращает константную ссылку, а один для случая - неизменный класс, возвращающий неизменяемую ссылку.

Вы заметите, однако, что помимо украшения метода все три реализации точно такие же. Для того, чтобы предотвратить вас от определения трех идентичных реализаций, D имеет inout модификатор:

RefType result() inout { 
    return test[0]; 
} 

Это единственное определение заменяет все три приведенных выше определений. Как правило, просто напишите свое определение как обычно, но разместите inout в любом месте, где вы бы разместили const.

+0

Хорошо, тогда у меня была путаница вчера. Я хочу, чтобы мой класс контейнера не мог быть изменен, но я не хочу, чтобы пользователи модифицировали объекты, которые хранятся в контейнере. Тогда в этом случае нет констант и неизменяемости. правильно? –

+0

@JairoAndresVelascoRomero Да, поскольку 'const' и' immutable' транзитивны в D, ни один из них не применяется к вашему прецеденту. Вам необходимо будет обеспечить неизменность самой коллекции на уровне API. –

+0

Когда вы возвращаете RefType, скорее всего, он должен быть 'inout' из-за транзитивных правил const - внутри метода const/immutable/inout, все, что они достигают через' this', имеет тот же тип (или более сильный). Кстати, жаль, что я сам не писал, был напряженным выходным. Но с этой маленькой нитью этот ответ должен быть хорошим. –

1

Я думаю, что opIndex() должен возвращать переменный тип RefType вместо значения по Const (переменный типа RefType), так как массив является массив! Переменным типа RefType.

Это предположение неверно. Поскольку ваш метод opIndex отмечен как const. Неявно заданная эта ссылка также является константой (is (const = const (MyContainer)). Это означает, что все, к чему вы обращаетесь через нее, также const, поскольку D's const является транзитивным. Когда вы получаете доступ к чему-то const в своем методе const, вы будете получить что-то const. Возвращение чего-то не-const из этого метода является незаконным в D (к счастью). Единственные вещи, которые не могут быть возвращены из метода const, - это типы значений без косвенности.

Действителен, чтобы вы вводили тип работать как неконстантный, const и неизменный вы можете написать:

inout(RefType) result() inout { ... } 
+0

Да, это путь. – DejanLekic