我必须遍历周边矩形的特定点(在某些情况下,我需要遍历此矩形的一行,在其他情况下,我需要遍历整个矩形)。我有一个PointIterator接口。
struct Point
{
double x,y
}
class PointIteratorI
{
virtual void next() =0;
virtual void isOver() =0;
virtual Point& getPoint() = 0;
}
如果迭代一行
class LineIterator:public PointIterator
{
....
}
在迭代矩形的周长的情况下
class PerimeterIterator:public PointIterator
{
....
}
对于LineIterator,我还需要线的类型(水平或垂直,矩形有2条水平线和2条垂直线)。
但是对于LineIterator类型,像“ getLineType”这样的接口就很奇怪。似乎此方法不适用于此类。因为在这种情况下,LineIterator类将负责迭代和定向。这违反了单一责任原则。
我以为不同的接口,如:
class LineObjectI
{
public:
virtual LineType getLineType() = 0;
.....
}
class LineIterator:public PointIterator, public LineObjectI
{
protected:
virtual LineType getLineType() = 0;
....
}
隐藏该界面。
我想知道是否有更好的方法来检查LineIterator上的线型。
最佳答案
我将提出不同的解决方案。放弃继承。
以boost::any
或std::any
开头。然后添加type erasure。
这是迭代器需要执行的3个操作:
const auto increment = make_any_method<void()>( [](auto&&self){++self;} );
const auto equals = make_any_method<bool(boost::any const&), true>( [](auto const&lhs, boost::any const& rhs){
using LHS=std::decay_t<decltype(lhs)> const;
auto prhs = boost::any_cast<LHS>(&rhs);
if (!prhs) return false;
return lhs == *prhs;
} );
template<class T>
const auto deref = make_any_method<T()>( [](auto&&self)->T {return *self;} );
现在,将这些操作转换为一个适当的迭代器,并进行一些操作:
template<class T,
class Base=super_any<decltype(increment), decltype(equals), decltype(deref<T>)>
>
struct poly_iterator:Base
{
using Base::Base;
using iterator_category = std::input_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T;
friend bool operator==( poly_iterator const& lhs, poly_iterator const& rhs ) {
return (lhs->*equals)(rhs);
}
friend bool operator!=( poly_iterator const& lhs, poly_iterator const& rhs ) {
return !(lhs==rhs);
}
T operator*() {
return ((*this)->*deref<T>)();
}
poly_iterator& operator++() {
((*this)->*increment)();
return *this;
}
poly_iterator operator++(int) {
std::cout << "i++\n";
auto copy = *this;
((*this)->*increment)();
return copy;
}
};
Live example。
boost
提供与类型T
类似的类型擦除迭代器系统。通常,此技术会对性能产生影响,因为在每个增量上跟随所有这些功能指针进行比较和取消引用的总和。
遍历许可者不是迭代的一种,它是迭代的范围。
遍历图的一侧(线)时也是如此。
有3种方法可以遍历整个外围。首先,遍历外围的线,然后遍历各个点。
其次,遍历外围点。
第三,迭代(side_type,point)或(side,point)对,其中side具有属性side_type。
这将导致与范围循环和C ++算法兼容的迭代,消除了使用智能指针的要求,并使您可以将迭代器视为值类型。它将类型系统移开:唯一拥有类型的东西就是要迭代的东西,而不是步行方式的细节。
关于c++ - 点迭代器的Wierd接口(interface)方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39518735/