用于std :: set或std :: vector的C ++迭代器

时间:2015-09-23 13:47:30

标签: c++ stl iterator

假设我有这个:

items

现在,在重构期间,我可能会在sorted_items中拥有内容,或者我可能会在HoldStuff holder; // assume it was filled earlier auto iter = holder.items.empty() ? holder.sorted_items.begin() : holder.items.begin(); auto iter_end = holder.items.empty() ? holder.sorted_items.end() : holder.items.end(); for (; iter != iter_end; ++iter) { auto& item = *iter; // Do stuff } 中拥有内容,但无论我想对每个项目执行相同的操作。我想做这样的事情:

justin bieber -sucks

当我去编译它时,我得到错误抱怨不兼容的操作数类型。当然这是可能的,不是吗?

4 个答案:

答案 0 :(得分:1)

您有两种选择:

  • 使用type-erasure在迭代器上获取运行时多态性(any_rangeany_iterator
  • do_stuff委托给采用任何迭代器的函数模板

以下是代码示例:

#include <vector>
#include <set>
#include <iostream>

#include <boost/range/any_range.hpp>

template<typename Iterator>
void do_stuff(Iterator begin, Iterator end) {}

int main()
{
  std::vector<int> items;
  std::set<int> sorted_items;
  // first option
  typedef boost::any_range<int, boost::forward_traversal_tag, int&, std::ptrdiff_t> my_any_range;
  my_any_range r;
  if(items.empty())
    r = my_any_range(sorted_items);
  else
    r = my_any_range(items);
  for (auto& x : r) {
    std::cout << x << " ";
  }

  // second option
  // this could also be a lambda and std::for_each
  if(items.empty())
    do_stuff(sorted_items.begin(), sorted_items.end());
  else
    do_stuff(items.begin(), items.end());
  return 0;
}

答案 1 :(得分:0)

错误是正确的: auto 关键字在编译期间有效。简单来说,它只是推断出分配的类型并使用这种真实类型。但是决定它的矢量迭代器还是设置是在运行时制作的。所以类型无法推断。 正如SergeyA所说,我在这里错了,编译器失败了?:运算符,在auto之前。但原因仍然相同 - 它不知道使用哪种类型的结果。

您应该使用一些更通用的迭代器类型+多态,或者您可以在类型上对此函数进行参数化,其中T是迭代器类型。我更愿意这样做:

template<class T> do_stuff(T &c) {  for (auto &el : c) { /*Whatever*/ } }

...

if (!items.empty()) {
    do_stuff(items);
} else if (!sorted_items.empty()) {
    do_stuff(sorted_items);
}     

P.S。:这是一个概念,我没有测试代码。

答案 2 :(得分:0)

三元运算符的两侧需要具有相同的类型。在你的情况下,它们是不同的 - std :: vector&lt;&gt; :: iterator和std :: set&lt;&gt;迭代器。一个合适的解决方案似乎是某种迭代器包装器,它根据初始条件返回一个或另一个。

答案 3 :(得分:0)

auto表示编译器将在编译时推断出后面的类型。

在这种情况下,三元条件运算符的返回类型是在问号后面,因此它是std::set<StuffItem, StuffItemComparator>::iterator并且编译器尝试将列(std::vector<StuffItem>::iterator)之后的内容转换为此不兼容类型因此编译错误。

您可以做的是让您的商品处理代码通用,如下所示:

auto doStuff = [] (StuffItem& item) {
  // do stuff with item...
};
if( holder.items.size() )
  for_each( holder.items.begin(), holder.items.end(), doStuff );
else if( holder.sorted_items.size() )
  for_each( holder.sorted_items.begin(), holder.sorted_items.end(), doStuff );