繁体   English   中英

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

[英]C++ Iterator for std::set or std::vector

假设我有这个:

struct HoldStuff {
  std::vector<StuffItem> items;
  std::set<StuffItem, StuffItemComparator> sorted_items;
}

现在,在重构期间,我可能在items包含东西,或者可能在sorted_itemssorted_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
}

当我去编译它时,我会抱怨关于不兼容的操作数类型的错误。 当然可以,不是吗?

您有两种选择:

  • 使用类型擦除在迭代器( 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;
}

错误是正确的: auto关键字在编译期间有效。 以一种简单的方式,它只是推导分配的类型并使用这种类型。 但是决定是向量的迭代器还是集合的迭代器是在运行时决定的。 因此无法推论类型。 正如SergeyA所说,我在这里错了,编译器在?:运算符上失败,然后自动。 但是原因仍然是相同的-它不知道要使用哪种类型的结果。

您可能应该使用一些更通用的迭代器类型+多态性,或者可以将此函数参数化为type,其中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);
}     

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

三元运算符的两端都必须具有相同的类型。 在您的情况下,它们是不同的-std :: vector <> :: iterator和std :: set <>迭代器。 合适的解决方案似乎是某种迭代器包装器,它会根据初始条件返回一个或另一个。

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

在这种情况下,三元条件运算符的返回类型是问号std::set<StuffItem, StuffItemComparator>::iterator因此它是std::set<StuffItem, StuffItemComparator>::iterator ,并且编译器将尝试std::vector<StuffItem>::iteratorstd::vector<StuffItem>::iteratorstd::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 );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM