45

Suppose I have an unordered set

unordered_set<int> my_set;
myset.insert(1);
myset.insert(2);
myset.insert(3);

How do I iterate through it? I don't need to iterate in any order - just as long as I reach each element once. I tried

for (int i = 0; i < my_set.size(); i++)
     cout << my_set[i];

to no avail.

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
dangerChihuahua007
  • 18,433
  • 28
  • 104
  • 190

3 Answers3

75

You can use the new range-based for loop:

std::unordered_set<T> mySet;
for (const auto& elem: mySet) {
    /* ... process elem ... */
}

Or, you can use the more traditional iterator-based loop:

std::unordered_set<T> mySet;
for (auto itr = mySet.begin(); itr != mySet.end(); ++itr) {
    /* ... process *itr ... */
}

Or, if you don't have auto support, perhaps because you don't have C++11 support on your compiler:

std::unordered_set<T> mySet;
for (std::unordered_set<T>::iterator itr = mySet.begin(); itr != mySet.end(); ++itr) {
    /* ... process *itr ... */
}

Hope this helps!

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
  • 4
    Why would boost's version of unordered_set break C++11's auto keyword? I think you mean, "...perhaps because you are using an older compiler," or something like that. – Marc Feb 05 '12 at 23:28
  • 2
    @Marc The question didn't actually say anything about C++11 originally; someone assumed it must be C++11 because `unordered_set` wasn't added till then, but Boost has one too, so the OP might be using an older C++ with the Boost `unordered_set` – Michael Mrozek Apr 03 '13 at 21:22
  • 4
    @MichaelMrozek True, but someone might use the boost version for other reasons while using a C++11 compiler. The text says "Or, if you don't have auto support, perhaps *because you're using the Boost version of unordered_set*", but `auto` is independent of the type used. The `auto` keyword will infer the type even for classes that have been untouched since before the '98 standard. As written, the answer makes it sound like auto only works for new classes, or must be designed into classes explicitly. It's a minor nit, but one I though worth clarifying. – Marc Apr 05 '13 at 18:22
9

Just like any other collection:

for (auto i = my_set.begin(); i != my_set.end(); ++i) {
    std::cout << (*i) << std::endl;
}

Or a bit more generic way using overloads of begin and end functions (you can write overloads for your own types; they also work on plain arrays):

for (auto i = begin(my_set); i != end(my_set); ++i) { 
    ...
}
Kos
  • 64,918
  • 23
  • 156
  • 223
  • for whatever reason my compiler (gcc) does not know what an "auto" is. Perhaps I should try "automobile", "vehicle" or "car"? :-) Now seriously: the answer below works like a charm. – Travis Banger Apr 13 '14 at 14:29
  • 1
    @TravisBanger Then you're probably running in C++98 mode, `auto` is only available from C++11 up. Use `--std=c++11` or name the iterator type explicitly (see @templatetypedef's answer) – Kos Apr 14 '14 at 08:11
3

Never used them so far, but I'd guess you can use an iterator the same way you do with std::set:

for(unordered_set<int>::iterator a = my_set.begin(); a != my_set.end(); ++a) {
    int some_int = *a;
}
Mario
  • 33,344
  • 5
  • 53
  • 74