Здравствуйте, drVanо, Вы писали:
V>Есть контейнер, который хранит указатели на объекты:
V> . . .
V>Есть некий базовый класс:
V>V>class BaseImportList : public ObjectList<BaseImport>
V>{
V>...
V>}
V>
V>И есть потомок, который хранит в контейнере предка от BaseImport:
V>V>class MacImport : public BaseImport
V>{
V>...
V>}
V>class MacImportList : public BaseImportList
V>{
V> typedef typename std::vector<MacImport *> list;
V> list::const_iterator begin() const { return reinterpret_cast<const list &>(items_).begin(); }
V> list::const_iterator end() const { return reinterpret_cast<const list &>(items_).end(); }
V>}
V>
V>Вопрос, как вытащить "std::vector" из ObjectList для приведения типов итератора чтобы больше никогда не зависеть от типа контейнера в базовом классе?
К сожалению, в C++ нет ковариантности контейнеров и не предвидится в обозримом будущем. Но в данном случае в ней (в ковариантности) нет и ососбой нужды. Насколько я могу судить по дизайну, класс MacImportList сам по себе имеет семантику контейнера, а значит, нет особого смысла выставлять наружу инкапсулированый контейнер, которые является деталью реализации класса. Достаточно просто предоставить адаптор итератора, который будет брать на себя преобразование к нужному типу. Схематично так:
template <typename T>
struct BaseImportListIteratorAdaptor : boost::iterator_adaptor<
BaseImportListIteratorAdaptor<T>, // This class
BaseImportList::const_iterator, // Base iterator
T*, // Value type
boost::use_default, // Category of traversal
T* // Reference (not allowing real references to pointers)
>
{
// Use concepts instead of the static_assert on C++20
static_assert(std::is_base_of_v<BaseImport, std::remove_pointer_t<std::decay_t<T>>>);
using BaseIterator = BaseImportList::const_iterator;
using BaseAdaptor = boost::iterator_adaptor<
BaseImportListIteratorAdaptor,
BaseImportList::const_iterator,
T*,
boost::use_default,
T*
>;
BaseImportListIteratorAdaptor() = default;
BaseImportListIteratorAdaptor(const BaseIterator& i) : BaseAdaptor(i) {}
T* dereference() const { return static_cast<T*>(*BaseAdaptor::base()); }
};
class MacImportList : public BaseImportList
{
public:
using const_iterator = BaseImportListIteratorAdaptor<MacImport>;
using iterator = const_iterator;
const_iterator begin() const { return items_.begin(); }
const_iterator end() const { return items_.end(); }
};
Ну а формирование инкапсулированного контейнера и его модификация должны проиводиться какими-то специализированными функциями. Прямого доступа на модификацию икапсулированного контейнера давать не следует.