Interfaces and covariance problem

前端 未结 5 2057
我在风中等你
我在风中等你 2021-01-05 07:29

I have a particular class that stores a piece of data, which implements an interface:

template
class MyContainer : public Container

        
5条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-05 08:05

    I would suggest a look at the Visitor pattern.

    Other than that, what you want is a value type that will be imbued with polymorphic behavior. There is a much simpler solution than James' using your IInterface.

    class IInterface
    {
      virtual ~IInterface() {}
      virtual void next() = 0;
      virtual void previous() = 0;
      virtual T* pointer() const = 0;
    
      virtual std::unique_ptr clone() const = 0;
    };
    
    std::unique_ptr clone(std::unique_ptr const& rhs) {
      if (!rhs) { return std::unique_ptr(); }
      return rhs->clone();
    }
    
    class Iterator
    {
      friend class Container;
    public:
      Iterator(): _impl() {}
    
      // Implement deep copy
      Iterator(Iterator const& rhs): _impl(clone(rhs._impl)) {}
      Iterator& operator=(Iterator rhs) { swap(*this, rhs); return *this; }
    
      friend void swap(Iterator& lhs, Iterator& rhs) {
        swap(lhs._impl, rhs._impl);
      }
    
      Iterator& operator++() { assert(_impl); _impl->next(); return *this; }
      Iterator& operator--() { assert(_impl); _impl->previous(); return *this; }
      Iterator operator++(int); // usual
      Iterator operator--(int); // usual
    
      T* operator->() const { assert(_impl); return _impl->pointer(); }
      T& operator*() const { assert(_impl); return *_impl->pointer(); }
    
    private:
      Iterator(std::unique_ptr impl): _impl(impl) {}
      std::unique_ptr _impl;
    };
    

    And finally, the Container class will propose:

    protected:
      virtual std::unique_ptr make_begin() = 0;
      virtual std::unique_ptr make_end() = 0;
    

    And implement:

    public:
      Iterator begin() { return Iterator(make_begin()); }
      Iteraotr end() { return Iterator(make_end()); }
    

    Note:

    You can do away with the std::unique_ptr if you can avoid the ownership issue. If you can restrict the IInterface to be behavioral only (by extracting the state into Iterator), then you can have the Strategy pattern kick-in, and use a pointer a statically allocated object. This way, you avoid dynamic allocation of memory.

    Of course, it means your iterators won't be so rich, as it requires IInterface implementations to be stateless, and implementing "filtering" iterators, for example, would become impossible.

提交回复
热议问题