如何在抽象 class 中声明 operator++(int)?
How to declare operator++(int) in an abstract class?
我有一个抽象 class 基本上是作为一个“迭代器接口”。也就是说,它是一个抽象的迭代器,稍后将由一些具体的 classes 实现。要使抽象 class 成为迭代器,我需要重载 T operator++(int)
,其中 T
是重载运算符的 class。
class AbstractClass {
virtual AbstractClass operator++(int) = 0; // compile time error
virtual AbstractClass& operator++() = 0; // but this is fine
}
但是,我不能写 AbstractClass operator++(int)
,因为只允许对抽象 class 的指针和引用作为 return 值。
有没有办法要求 subclasses 在纯 C++11 中重载 operator++(int)
?
具有 virtual
成员的抽象 classes 通常通过基指针访问,因此您的调用者不知道派生类型,但 return 来自 [=12] 的值=] 调用者必须在编译时知道,因此无法直接执行此操作。我根本不会提供这种方法,让你的 class 像迭代器一样,但不完全符合迭代器。
但是,有一个复杂的解决方法,那就是创建一个本身可以将虚拟迭代器作为成员处理的非抽象迭代器。这变得超级复杂。
//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;}
};
除了复杂性之外,这还会在堆上分配迭代器,这使得它们非常慢。
另请注意:virtual
成员阻止内联和优化,因此使代码变慢。对于像迭代器这样应该是轻量级的东西,这实际上会使代码变慢 很多。
我有一个抽象 class 基本上是作为一个“迭代器接口”。也就是说,它是一个抽象的迭代器,稍后将由一些具体的 classes 实现。要使抽象 class 成为迭代器,我需要重载 T operator++(int)
,其中 T
是重载运算符的 class。
class AbstractClass {
virtual AbstractClass operator++(int) = 0; // compile time error
virtual AbstractClass& operator++() = 0; // but this is fine
}
但是,我不能写 AbstractClass operator++(int)
,因为只允许对抽象 class 的指针和引用作为 return 值。
有没有办法要求 subclasses 在纯 C++11 中重载 operator++(int)
?
具有 virtual
成员的抽象 classes 通常通过基指针访问,因此您的调用者不知道派生类型,但 return 来自 [=12] 的值=] 调用者必须在编译时知道,因此无法直接执行此操作。我根本不会提供这种方法,让你的 class 像迭代器一样,但不完全符合迭代器。
但是,有一个复杂的解决方法,那就是创建一个本身可以将虚拟迭代器作为成员处理的非抽象迭代器。这变得超级复杂。
//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;}
};
除了复杂性之外,这还会在堆上分配迭代器,这使得它们非常慢。
另请注意:virtual
成员阻止内联和优化,因此使代码变慢。对于像迭代器这样应该是轻量级的东西,这实际上会使代码变慢 很多。