0

我正在尝试实现不同版本的数据结构。假设它有一个如下所示的界面(它被简化了):

template <typename T>
class Base {
 public:
  class Iterator {
    virtual auto operator*() -> T& = 0;
  };

 public:
  virtual auto Find(const T& value) -> Iterator = 0;
}

现在我想继承一个将实现它的类:

template <typename T>
class Derived : public Base<T> {
 public:
  class Iterator {
    auto operator*() -> T& override {
      /* ... */
    }
  };

 public:
  auto Find(const T& value) -> Iterator override {
    /* ... */
  };
}

问题是我需要Iterator基于什么来实现Derived,但是Find函数的签名因为Derived::Iterator(应该是Base::Iterator)而刹车。有没有办法这样做还是我必须放弃使用接口类?

4

1 回答 1

0

据我了解,您要实现的目标与类型擦除或静态多态性有关。您希望 Base::Iterator 是非抽象的通用类型,可以从任何 Derived 实现构造。

这是一个动态解决方案,您可以根据自己的需要进行优化

template<typename T>
struct Base
{
// This is the interface that needs to be implemented by the derrived classe's iterator
    struct IIterator
    {
        virtual T& Get() = 0;
    };
// this is the generalized type that needs to be returned by find()
    struct Iterator
    {
        Iterator(std::unique_ptr<IIterator> impl ):
            _impl(std::move(impl))
        {
        }

        T& operator*() { _impl->Get(); }

        private:
// You can implement small struct optimization by making a byte array big enough
// to store any of the implementations and avoid dynamic memory
        std::unique_ptr<IIterator> _impl;
    };

    virtual Iterator find() = 0;
};

template<typename T>
struct Derived : public Base<T>
{
// Now in derived we implement our iterator
    struct IteratorImpl : Base<T>::IIterator
    {
        IteratorImpl(T* p) : ptr(p) {}

        T& Get() override { return *ptr; }
        T* ptr;
    };

    typename Base<T>::Iterator find() override
    {
        IteratorImpl result(nullptr);
// After finding we need to construct the generalized type from the implementation
        return typename Base<T>::Iterator(std::make_unique<IteratorImpl>( result ));
    }
};

另一种方法是使用模板和 CRTP 来制作静态界面。CRTP 是一种技术,它涉及使用它的模板参数将派生类型信息传递回基类,并使用该信息来定义或查找基于派生类型的 Base 迭代器的实现。

于 2020-07-19T19:22:00.920 回答