Reputation: 1244
If I have a std::set::iterator
, how do I quickly produce an iterator which points to the next element in the set? A specific use-case for this general question follows:
Suppose I have a std::set
, and I want to print out all pairs of distinct elements in the set. I believe that I can't write things like my_set.begin() + 1
, because the iterator produced by set
is not capable of arithmetic (unlike say that produced by a vector
). So how can I achieve this?
The solution I came up with is
int main(){
set<int> my_set {1,4,6};
for (auto it = my_set.begin(); it != my_set.end(); it++) {
int first_number = *it;
for (auto it2 = it; it2!= my_set.end(); it2++) {
if (it2 == it){it2++;} // I don't want the second number to be equal to the first
if (it2 == my_set.end()) {break;} //If I don't put this in, it will eventually try to access my_set.end(), giving bad behavior.
int second_number = *it2;
cout << "(" << first_number << ", " << second_number << ")" << endl;
}
}
return 0;
}
Output:
(1, 4)
(1, 6)
(4, 6)
Program ended with exit code: 0
But this is kludgy, I think, to have to manually iterator it2, and then check it hasn't become my_set.end()
. How can I do it better?
I tried making the it2 loop look like
for (auto it2 == it; it2!= my_set.end(); it2++) {...
to make it start with it2
one bigger than it
, but it was not happy with this syntax.
Apologies if this question has appeared before. I wasn't able to find it.
Upvotes: 2
Views: 1673
Reputation: 155363
std::next
can be used to get a new iterator that is advanced relative to an existing iterator in one call (if the second argument isn't passed, it's advanced exactly once), so your code should be possible with just:
#include <iterator> // For std::next
int main(){
set<int> my_set {1,4,6};
for (auto it = my_set.begin(); it != my_set.end(); ++it) {
int first_number = *it;
for (auto it2 = std::next(it); it2 != my_set.end(); ++it2) {
int second_number = *it2;
cout << "(" << first_number << ", " << second_number << ")" << endl;
}
}
return 0;
}
Note that I also changed your it++
/it2++
expressions to ++it
/++it2
; for iterators, this can be important for performance, as postfix increment necessarily makes new iterator objects to return, while prefix increment can modify the iterator in place much more cheaply (returning only a reference to the iterator itself, no copies needed).
Upvotes: 4