[英]Inheriting a abstract iterator interface
我想为容器类继承一个迭代器。 它应始终具有与实际实现无关的相同签名。
但我在这个问题ContainerImpl
返回的Container::Iterator
从ContainerImpl::begin()
切片从覆盖的方法ContainerImpl::Iterator
返回的那些Container::Iterator
。
如何强制使用更具体的方法? 还是可以重写我的类,使其表现得像那样?
下面是一个工作示例。 它至少针对C ++ 17进行编译。
#include <tuple>
using std::tuple;
class Container {
// some code
public:
class Iterator {
public:
virtual tuple<int, int> &operator*() {};
virtual Iterator &operator++() {};
virtual bool operator!=(const Iterator &rhs) const {};
};
virtual Iterator begin() = 0;
virtual Iterator end() = 0;
};
class ContainerImpl : public Container {
// some code
public:
class Iterator : public Container::Iterator {
public:
Iterator(ContainerImpl &containerImpl) {
// init
}
Iterator() {
// end_iterator
}
virtual tuple<int, int> &operator*() override {
// impl
};
virtual Container::Iterator &operator++() override {
// impl
};
virtual bool operator!=(const Container::Iterator &rhs) const override {
// impl
};
};
virtual Container::Iterator begin() override {
return Iterator{*this};
};
virtual Container::Iterator end() override {
return Iterator{};
};
};
int main() {
ContainerImpl cont{};
for (auto &entry : cont) {
// here Container::Iterator::operator++() is called
// instead of ContainerImpl::Iterator::operator++()
}
}
编辑:
谢谢! 我通读了您的评论,并发现我应该尝试使用模板的静态方法。 对于那些迭代器,性能非常重要。 这将需要在我使用此代码的地方重构其他代码。 但这应该适中。
这是我想出的:
#include <tuple>
#include <type_traits>
using std::tuple;
template<class SubContainer>
class Container;
template<class ContImpl>
class Iterator {
static_assert(std::is_base_of<Container<ContImpl>, ContImpl>::value, "ContImpl not derived from Container");
public:
tuple<int, int> &operator*();
Iterator<ContImpl> &operator++();
bool operator!=(const Iterator<ContImpl> &rhs) const;
};
template<class SubContainer>
class Container {
public:
Iterator<SubContainer> begin();
Iterator<SubContainer> end();
};
class ContImpl;
template<>
class Iterator<ContImpl> {
public:
ContImpl &container;
Iterator(ContImpl &container, bool is_end = false) : container(container) { init(); }
void init() {
}
tuple<int, int> &operator*() {
}
Iterator<ContImpl> &operator++() {
}
bool operator!=(const Iterator<ContImpl> &rhs) const {
}
};
class ContImpl : public Container<ContImpl> {
public:
Iterator<ContImpl> begin() {
return Iterator<ContImpl>(*this, false);
}
Iterator<ContImpl> end() {
return Iterator<ContImpl>(*this, true);
}
};
int main() {
ContImpl cont{};
for (auto &entry : cont) {
// Iterator<ContImpl>::operator++() is called.
}
}
如果您想动态地抽象出例如std::list<int>
和std::vector<int>
之间的差异,那么您想要的就是类型Erase 。 但是请注意,使用模板模板参数之类的东西,还可以对具有相似接口(具有相同或不同元素类型)的容器进行静态抽象,这(如果满足您的要求)应该更快。
关于基于模板的方法:虽然它可能具有文档价值,但Container
中的方法是不必要的:静态多态不需要任何“基本函数”来覆盖。 如果删除它们,则可以完全不用该CRTP类。 然后,类似地,您可以用简单的类ContImpl::iterator
替换Iterator
类模板。
当然,到那时,剩下的就是与标准容器之间相同的接口兼容性(它允许类似
template<template<class> class C>
C<int> makeInts(/*...*/);
void f() {
auto d=makeInts<std::deque>(/*...*/);
// ...
}
我在上面建议)。 有趣的练习是在包装器类后面或使用traits接口隐藏另一个容器接口。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.