Учитывая следующий класс, основанный на контейнерах общих указателей,
class Foo;
class Bar {
public:
// ...
const std::vector<boost::shared_ptr<const Foo> >& getFoos() const { return foos_; }
private:
std::vector<boost::shared_ptr<Foo> > foos_;
};
который не будет компилироваться, потому что
invalid initialization of reference of type ‘const std::vector<boost::shared_ptr<const Foo>, std::allocator<boost::shared_ptr<const Foo> > >&’ from expression of type ‘const std::vector<boost::shared_ptr<Foo>, std::allocator<boost::shared_ptr<Foo> > >’
foos_
член должен указывать на изменчивый Foo
объекты для внутреннего использования Bar
объект, но я не хочу вызова клиентского кода getFoos()
чтобы иметь возможность что-либо изменить.
Удаление const
классификатор из Foo
в getFoos()
возвращаемый тип исправляет это. Тем не менее, я понимаю, что пока std::vector
распространяет свою константность своим элементам, boost::shared_ptr
не делает ничего подобного объекту, на который он указывает (естественно). Таким образом, мне кажется getFoos()
больше не наблюдает его const
квалификатор (хотя компилятор не жалуется), потому что клиентский код может изменить Foo
объекты, на которые указывают общие указатели, возвращаются.
Я прав? Если так, есть ли способ написать getFoos()
чтобы он возвращал константный вектор константных ссылок на константные объекты без копирования?
Я могу ошибаться, но я действительно не думаю, что вы можете достичь этого.
shared_ptr<Foo>
может стать shared_ptr<const Foo>
только путем строительства нового экземпляра shared_ptr<const Foo>
Ссылка на shared_ptr<Foo>
не может стать ссылкой на shared_ptr<const Foo>
просто потому что они два разные типы.
Здесь вы пытаетесь получить ссылку на vector<shared_ptr<Foo>>
в форме const vector<shared_ptr<const Foo>>
,
Первый const
отлично в порядке. Так как можно назначить ссылку на тот же тип ссылки с помощью квалификатора const.
Но второе const
нет, так как вы буквально пытаетесь преобразовать ссылку на вектор Type A
к ссылке на вектор Type B
,
Вместо возврата std::vector<...> const&
что насчет возврата диапазона? Диапазон pair
итераторов некоторого вида. В этом случае ваши итераторы будут std::shared_ptr<const foo>
, Вы можете сделать это, написав быстрый адаптер итератора, который внутренне перебирает const_iterator
в std::shared_ptr<foo>
, но возвращает их как std::shared_ptr<const foo>
,
Большинство операций, которые вы хотите выполнить на const
vector
может быть выполнен на range
произвольного доступа const_iterator
s.
Вы можете вернуть const shared_ptr<Foo>*
указатель вместо вектора и использование явного уродливого приведения в стиле C для преобразования foos_.data()
во все, что вы хотите.
Поскольку вы заинтересованы в возврате константного вектора, вы не теряете много, возвращая указатель, за исключением, конечно, информации о размерах. Вы всегда можете заключить новый указатель в класс, предназначенный для предоставления этой информации о размерах, которая предоставляется в момент ее создания.