Поскольку у вас есть два уровня косвенности - в вашей основной функции этот вызов value
возвращает ссылку на указатель const на неконстантный foo
.
Это можно безопасно скопировать в неконстантный указатель на неконстантный foo
.
Если вы создали экземпляр test
с const foo *
, это будет другая история.
const test<const foo*> t;
foo* f = t.value(); // error
const foo* f = t.value(); // fine
return 0;
Update
Из комментария:
значение() возвращает сопзЬ T &, которые могут быть назначены только на другой сопзЬ типа. Но в этом случае компилятор безопасно разрешает преобразование.
Данные константы могут быть прочитаны. Он не может быть записан («мутирован»). Но копирование некоторых данных - это способ их чтения, так что все в порядке. Например:
const int c = 5;
int n = c;
Здесь я имел некоторые константные данные в c
, и я скопировать данные в неконстантный переменной п. Все в порядке, это просто чтение данных. Значение в c
не было изменено.
Теперь предположим, что ваши foo
имели некоторые данные в нем:
struct foo { int n; };
Если у меня есть неконстантную указатель на одну из тех, что я могу изменить значение n
через указатель. Вы спросили свой шаблон test
для хранения указателя на неконстантный foo
, а затем сделали экземпляр const из test
. Поэтому всегда указывается адрес указателя. Никто не может изменить адрес, хранящийся в указателе внутри test
, поэтому его нельзя указать на другой объект. Однако объект, на который он указывает, может изменить его содержимое.
Update 2:
Когда вы сделали свою версию без шаблона из примера, вы сделали ошибку. Чтобы все было правильно, вам нужно заменить foo *
на каждое место, где есть T
.
const T& value() const
Обратите внимание, что у вас есть ссылка на const T
. Таким образом, возвращаемое значение будет ссылкой на что-то const: a foo *
. Только адрес указателя не может быть изменен. Объект, на который он указывает, может изменить его содержимое.
В вашем втором примере вы избавились от ссылочной части, которая изменяет значение и делает модификатор const
применимым к объекту, на который указывает указатель, вместо того, чтобы применять его к самому указателю.
Спасибо. Но я все еще недостаточно ясен. IMO-мнение, 'value()' возвращает 'const T &', который может быть назначен только другому типу 'const'. Но в этом случае компилятор безопасно разрешает преобразование. Также в моем случае я не могу выполнить 'test'. –
@Appu Это отличается от указателя на const и const указателем на non-const. Не знаю, почему вы не можете «сделать» 'test'. –
См. Редактирование. У меня есть неконстантный член 'f' и возвращающий' const' из него. В этом случае компиляция испрашивается правильно. Похоже, что поведение отличается при использовании шаблонов. –