Поскольку у вас есть два уровня косвенности — в вашей основной функции этот вызов 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() возвращает константу T&, которую можно присвоить только другому константному типу. Но в этом случае компилятор спокойно разрешает преобразование.
Постоянные данные можно только читать. Оно не может быть записано («мутировано»). Но копирование некоторых данных — это способ их чтения, так что все в порядке. Например:
const int c = 5;
int n = c;
Здесь у меня были некоторые константные данные в c
, и я скопировал данные в неконстантную переменную n. Это нормально, он просто читает данные. Значение в c
не было изменено.
Теперь предположим, что в вашем foo
есть данные:
struct foo { int n; };
Если у меня есть неконстантный указатель на один из них, я могу изменить значение n
с помощью указателя. Вы попросили свой шаблон test
сохранить указатель на неконстантный foo
, а затем создали константный экземпляр test
. Следовательно, только адрес указателя является постоянным. Никто не может изменить адрес, хранящийся в указателе внутри test
, поэтому его нельзя заставить указывать на другой объект. Однако объект, на который он указывает, может изменить свое содержимое.
Обновление 2:
Когда вы сделали версию примера без шаблона, вы допустили ошибку. Чтобы сделать это правильно, вам нужно подставить foo *
в каждое место, где есть T
.
const T& value() const
Обратите внимание, что у вас есть ссылка на константу T
. Таким образом, возвращаемое значение будет ссылкой на что-то константное: foo *
. Это только адрес указателя, который не может быть изменен. Объект, на который он указывает, может изменить свое содержимое.
Во втором примере вы избавились от ссылочной части, которая меняет значение и заставляет модификатор const
применяться к объекту, на который указывает указатель, а не к самому указателю.
person
Daniel Earwicker
schedule
20.02.2010