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