[英]C++ Iterator for std::set or std::vector
假设我有这个:
struct HoldStuff {
std::vector<StuffItem> items;
std::set<StuffItem, StuffItemComparator> sorted_items;
}
现在,在重构期间,我可能在items
包含东西,或者可能在sorted_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
}
当我去编译它时,我会抱怨关于不兼容的操作数类型的错误。 当然可以,不是吗?
您有两种选择:
any_range
或any_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>::iterator
列std::vector<StuffItem>::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 );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.