2016-01-22 46 views
1

让我们来考虑一个非常基本的范围适配器类,它围绕一个范围进行打包,并在遍历适配器时迭代原始范围的每个其他元素。在范围适配器的迭代器类中实现运算符 - >

for (const auto & e : everyOtherElement(originalRange)) 

当写这样的范围适配器类,需要编写一个相应的迭代器类为该适配器,使其可迭代和行为像期望的。

这样的迭代器类应该实现您希望它支持的“概念”所需的所有内容,例如InputIterator。除其他外,我们应该执行operator*以返回对代表元素的引用,以及operator->,以便it->member访问该元素的成员。

我认为这将是一个好主意,只是“前进”这些运营商底层迭代器适配器环绕的实现(让我们忘掉常量性了一会儿):

struct everyOtherElement { 
    OriginalIterator b, e; // The begin and end we wrap around 
    // ... 
    struct iterator { 
     OriginalIterator it; 
     auto operator*() { return *it; }     // <------ 
     auto operator->() { return it.operator->(); }  // <------ 
     // ... 
    }; 
}; 

但是,如果OriginalIterator是指针类型,则operator->无法编译,就像大多数std::vector实现以及原始数组一样。由于这种迭代器是非类型的,因此不允许编写it.operator->()

我该如何实现operator->才能使迭代器尽可能透明?我是否应该按照operator*执行operator->,即像编写(*it).m而不是it->m。我猜这会失败,如果一些迭代器实现它们意味着不同的事情...(虽然这将是邪恶的,不是吗?或者被InputIterator概念禁止?)

它是一个好主意来实现它作为刚刚返回的原始迭代器,因为operator->是递归自动应用,只要返回一个非指针?

 auto operator->() { return it; } 
+0

正如我假设有涉及模板,我会建议仅使用SFINAE /标签调度来选择实现,具体取决于OriginalIterator是否为指针。 –

回答