перебирая контейнер объектов из иерархии наследования, скрывая указатели - PullRequest
0 голосов
/ 31 января 2019

Проблема, с которой я сталкиваюсь, заключается в следующем: у меня есть иерархия наследования объектов, и я хочу определить класс, представляющий коллекцию объектов из этой иерархии, которые могут иметь разные динамические типы.Мне интересно, есть ли способ создать и повторить такую ​​коллекцию, скрывая тот факт, что она содержит указатели.В настоящее время мой код можно резюмировать следующим образом:

class Base{
    public:
       virtual Base* clone() const & { return new Base(*this); }
       virtual Base* clone() && { return new Base( std::move(*this) ); }
    ... other members ...

};

class Derived : public Base{
    public: 
        Derived* clone() const & override { return new Derived(*this); }
        Derived* clone() && override { return new Derived( std::move(*this) ); }
    ... other members ...
};

class ObjectCollection{
    public:
        ... constructor and other members...

        // use 'clone' function to initialize the collection without having to pass pointers
        void push_back( const Base& );
        void push_back( Base&& );

        using iterator = std::vector< std::shared_ptr< Base > >::iterator
        using const_iterator = std::vector< std::shared_ptr< Base > >::const_iterator

        iterator begin(){ return collection.begin(); }
        const_iterator begin() const{ return collection.cbegin(); }

        iterator end() { return collection.end(); }
        const_iterator end() const{ return collection.cend(); }
    private: 
        std::vector< std::shared_ptr< Base > > collection;
};

//loop over objects:
ObjectCollection collection(...call to constructor...);
for( auto & object : collection ){
    //object is now a reference to shared_ptr to Object rather than a reference to Object!
}

В идеале я хотел бы иметь возможность написать цикл for, подобный последнему, где я могу получать ссылки на объекты напрямую, а не на указатели.Есть ли способ добиться этого?Или лучше продолжать работать с указателями?(Примечание: один из известных мне способов решения проблемы, но которого я бы хотел избежать, - это перегрузить оператор [] для разыменования указателей).

1 Ответ

0 голосов
/ 31 января 2019

С range-v3 вы можете создать справочный вид вашей коллекции shared_ptr:

auto get_collection_view() /*const*/
{
    return collection | ranges::v3::transform([](auto&& p) -> /*const*/ Base& { return *p; });
}
...