Прежде всего, давайте поговорим о shared_ptr
. Знаете ли вы о: boost::detail::dynamic_cast_tag
?
shared_ptr<Foo> fooPtr(new Bar());
shared_ptr<Bar> barPtr(fooPtr, boost::detail::dynamic_cast_tag());
Это очень удобный способ. Под прикрытием он просто выполняет dynamic_cast
, ничего особенного, кроме более простой записи. Контракт такой же, как и классический: если указанный объект на самом деле не является Bar
(или получен из него), то вы получите нулевой указатель.
Вернуться к вашему вопросу: ПЛОХОЙ КОД.
BarCollection
НЕ является FooCollection
, как уже упоминалось, у вас возникли проблемы, потому что вы могли бы ввести другие элементы в вектор указателей, такие как Bar
.
Я не буду останавливаться на этом, хотя, потому что это выходит за рамки рассматриваемого вопроса, и я думаю, что мы (как те, кто пытается ответить) должны сдерживать себя от этого.
Вы не можете передать ссылку, но вы можете передать View
.
По сути, View
- это новый объект, который действует как Proxy
для старого. Относительно легко использовать Boost.Iterators из примера.
class VectorView
{
typedef std::vector< std::shared_ptr<Foo> > base_type;
public:
typedef Bar value_type;
// all the cluttering
class iterator: boost::iterator::iterator_adaptor<
iterator,
typename base_type::iterator,
std::shared_ptr<Bar>
>
{
typename iterator_adaptor::reference dereference() const
{
// If you have a heart weakness, you'd better stop here...
return reinterpret_cast< std::shared_ptr<Bar> >(this->base_reference());
}
};
// idem for const_iterator
// On to the method forwarding
iterator begin() { return iterator(m_reference.begin()); }
private:
base_type& m_reference;
}; // class VectorView
Настоящая проблема здесь, конечно, reference
бит. Получить объект NEW
shared_ptr
легко и можно выполнить dynamic_cast
по мере необходимости. Получение reference
до ORIGINAL
shared_ptr
, но интерпретируемого как требуемый тип ... это действительно не то, что мне нравится видеть в коде.
Примечание
Возможно, есть способ добиться большего успеха, чем при использовании класса Boost.Fusion transform_view , но я не могу понять это.
В частности, используя transform_view
, я могу получить shared_ptr<Bar>
, но не могу получить shared_ptr<Bar>&
, когда разыменую свой итератор, что раздражает, учитывая, что единственное использование - возвращение ссылки на базовый vector
(а не const_reference
) - фактически изменить структуру vector
и объектов, которые он содержит.
Примечание 2 :
Пожалуйста, подумайте о рефакторинге. Там были отличные предложения.