对于像 std::set<std::string> set={ "aaa", "bbb", "ccc", "ddd", "eee", "fff" };
这样的 std::set
如何在不跟踪额外索引的情况下迭代此集合的特定范围 [a, b]?
像这样:
for(auto it = set.begin(); it!=set.begin()+b; ++it)
std::cout << *it << " ";
或者像这样:
for(auto it = set.begin()+a; it!=set.begin()+b; ++it)
std::cout << *it << " ";
其中 a<=b
和 b<=set.size()
答案 0 :(得分:3)
你不能做set.begin()+a
,但你可以做std::advance(it, a)
:
#include <iostream>
#include <set>
#include <string>
int main()
{
std::set<std::string> set={ "aaa", "bbb", "ccc", "ddd", "eee", "fff" };
size_t a = 1, b = 4;
auto it = set.begin(), it_end = set.begin();
std::advance(it, a);
std::advance(it_end, b);
for(; it!= it_end; ++it)
std::cout << *it << " ";
}
不幸的是,您不能执行 auto it = std::advance(set.begin(), a);
之类的操作,因为 advance
通过引用获取迭代器并对其进行了更改。
更好的解决方案使用 std::next
,感谢@Evg:
#include <iostream>
#include <set>
#include <string>
int main()
{
std::set<std::string> set={ "aaa", "bbb", "ccc", "ddd", "eee", "fff" };
size_t a = 1, b = 4;
for(auto it = std::next(set.begin(), a), it_end = std::next(it, b-a); it != it_end; ++it)
std::cout << *it << " ";
}
答案 1 :(得分:1)
您可以编写自己的 slice
类,有点像 std::span
:
#include <cstdio>
#include <set>
#include <string>
template <class Iter>
class slice {
private:
Iter _beg;
Iter _end;
public:
slice(Iter beg, Iter end) noexcept
: _beg{beg}
, _end{end}
{}
slice(Iter beg, std::size_t sz) noexcept
: slice(beg, std::next(beg, sz))
{}
auto begin() const noexcept { return _beg; }
auto end() const noexcept { return _end; }
};
int main() {
std::set<std::string> const set{"aaa", "bbb", "ccc", "ddd", "eee", "fff"};
slice const sl(set.begin(), 3);
for (auto const& elm : sl) std::puts(elm.c_str());
}