简体   繁体   English

如何在抽象 class 中声明 operator++(int)?

[英]How to declare operator++(int) in an abstract class?

I have an abstract class that is basically meant to serve as an "iterator interface".我有一个抽象的 class ,它基本上是作为一个“迭代器接口”。 That is, it is an abstract iterator that a few concrete classes will later implement.也就是说,它是一个抽象的迭代器,稍后将由一些具体的类来实现。 To make the abstract class an iterator, I need to overload T operator++(int) , where T is the class for which the operator is overloaded.要使抽象 class 成为迭代器,我需要重载T operator++(int) ,其中T是运算符重载的 class。

class AbstractClass {
    virtual AbstractClass operator++(int) = 0; // compile time error
    virtual AbstractClass& operator++() = 0;   // but this is fine
}

However, I cannot write AbstractClass operator++(int) as only pointers and references to an abstract class are permitted as return values.但是,我不能编写AbstractClass operator++(int) ,因为只允许将指针和对抽象 class 的引用作为返回值。

Is there a way to require the subclasses to overload operator++(int) in plain C++11?有没有办法要求子类在普通 C++11 中重载operator++(int)

Abstract classes with virtual members are usually accessed through base pointers, so you teh caller doesn't know the derived type, but the return value from operator++(int) must be known at compile time by the caller, so there's no way to do this directly.具有virtual成员的抽象类通常通过基指针访问,所以调用者不知道派生类型,但是调用者必须在编译时知道operator++(int)的返回值,所以没有办法做到这一点直接地。 I would simply not provide this method, and have your class be iterator-like, but not fully iterator-conforming.我根本不会提供这种方法,并让您的 class 像迭代器一样,但不完全符合迭代器。

However, there is a complex workaround, and that's to make a non-abstract iterator that itself can handle a virtual iterator as a member.但是,有一个复杂的解决方法,那就是创建一个本身可以将虚拟迭代器作为成员处理的非抽象迭代器。 This gets super complicated.这变得超级复杂。

//abstract interface for iterators
template<class value_type>
struct virtual_iterator_interface {
    virtual ~virtual_iterator_interface(){};
    virtual std::unique_ptr<virtual_iterator_interface> clone()const=0;
    virtual value_type& deref()=0;
    virtual void increment()=0;
};
//wrapper implementation for iterators
template<class value_type, class It>
struct virtual_iterator : virtual_iterator_interface<value_type> {
    It it;
    virtual_iterator(It it_) : it(it_) {}
    std::unique_ptr<virtual_iterator_interface> clone()const
    {return std::make_unique<virtual_iterator>(it);}
    value_type& deref()
    {return *it;}
    void increment()
    {return ++it;}
};

static const struct from_iterator_t {} from_iterator;
// The iterator that holds a pointer to an abstracted iterator
template<class value_type>
class erased_iterator {
    std::unique_ptr<virtual_iterator_interface<value_type>> ptr;
public:
    template<class It>
    erased_iterator(from_iterator_t, It it)
    :ptr(std::make_unique<virtual_iterator<value_type,It>>(it)) {}
    erased_iterator(std::unique_ptr<virtual_iterator_interface<value_type>> ptr_)
    :ptr(std::move(ptr_)) {}
    erased_iterator(const erased_iterator& rhs)
    :ptr(rhs.ptr->clone()) {}
    erased_iterator(erased_iterator&& rhs) = default;
    erased_iterator& operator=(const erased_iterator& rhs)
    {ptr=rhs.ptr->clone();}
    erased_iterator& operator=(erased_iterator&& rhs) = default;

    //TADA! Iterator things are now possible!
    value_type& operator*(){return ptr->deref();}
    erased_iterator& operator++(){ptr->increment(); return *this;}
    erased_iterator operator++(){erased_iterator t(it->clone()); ptr->increment(); return t;}
};

In addition to complexity, this allocates iterators on the heap, which makes them very slow.除了复杂性之外,这还会在堆上分配迭代器,这使得它们非常慢。

Also note: virtual members prevent inlining and optimization, so makes the code slower.另请注意: virtual成员会阻止内联和优化,因此会使代码变慢。 For things like iterators, which are supposed to be lightweight, this can actually make the code a lot slower.对于像迭代器这样应该是轻量级的东西,这实际上会使代码变慢很多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM