std::set或std::vector的迭代器
C++ Iterator for std::set or std::vector
我们设这个:
struct HoldStuff {
std::vector<StuffItem> items;
std::set<StuffItem, StuffItemComparator> sorted_items;
}
现在,在重构过程中,我可能在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;
}
三元操作符的两边必须具有相同的类型。在您的例子中,它们是不同的——std::vector<>::iterator和std::set<> iterator。一个合适的解决方案似乎是某种迭代器包装器,根据初始条件返回一个或另一个。
错误是正确的:auto关键字在编译过程中工作。简单地说,它只是推导出赋值的类型,并使用这个实类型。但是决定它是vector的迭代器还是set的迭代器是在运行时做出的。所以类型不能被推断出来。正如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);
}
注::这是一个概念,我没有测试代码
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 );
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在c++迭代器类型中包装std::chrono
- std::vector::迭代器是否可以合法地作为指针
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?
- 如何在创建自定义迭代器时获得 std::p air 的第一个和第二个?
- 修改 std::vector 会使迭代器无效吗?
- std::list 中的迭代器感知对象
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- 为什么 std::迭代器被弃用?
- std::迭代器是否可以检查该迭代器上是否存在下一个元素?(此设计受到家庭作业的限制)
- std::迭代器到自身的映射
- std::迭代器的准备工作已弃用
- std::迭代器、指针和 VC++ 警告 C4996
- 指向指针的STD迭代器;为应该是等价的代码获取不同的类型
- C++ std::迭代器何时以及如何使用value_type、引用、指针
- C++ std::迭代器,内部不使用 std::vector 或 std::list
- 传递std::迭代器,指向具有特征类型的向量
- 在c++中通过std迭代器将基类强制转换为派生类