const Iterator& begin() const {
return s.begin(); //** error
}
недопустимо, поскольку результат s.begin()
является временным объектом, и поэтому вы не можете вернуть ссылку на него. Может быть, если вы посмотрите на этот эквивалентный код, он будет понятнее?
const Iterator& begin() const {
Iterator it = s.begin();
return it; //** error
}
Возвращение константной ссылки на итератор в любом случае не имеет особого смысла, так как вы не сможете переместить местоположение, на которое указывает итератор. Вы должны всегда возвращать итераторы по значению, таким образом, вызывающая сторона может свободно делать копии итератора и изменять их местоположение. Например, если бы вы могли заставить свой код скомпилировать следующий код вызова, это не сработало бы:
Pool p;
const Pool::Iterator& it = p.begin();
++it; //error it is constant
Пользователь может исправить свой код, скопировав возвращенную ссылку в новый объект:
Pool p;
Pool::Iterator it = p.begin();
++it; //no error
Поскольку ваши пользователи не смогут использовать ссылку, вы не можете вернуть ее лучше, просто чтобы вернуться по значению:
const Iterator begin() const {
return s.begin();
}
Обратите внимание, что std::set
не похож на большинство других контейнеров и не позволяет изменять значения через его итераторы: https://en.cppreference.com/w/cpp/container/set/begin
Поскольку итератор и const_iterator являются постоянными итераторами (и на самом деле могут быть одного типа), невозможно изменить элементы контейнера с помощью итератора, возвращаемого любой из этих функций-членов.