In order to provide constant amortized time for item membership checking, which is the advantage of an unordered set, for the general case of some arbitrary item type it has to be implemented as a hash table.
It's not difficult to ensure, in constant time, that every key (item) in a hash table is also referred to by a node of a linked list. This provides a means to iterate over the items in the table, in unspecified order. However, going to the i-th item in a linked list is linear time.
There is a compromise solution where as each item is added to the hash table, it's also added to a sorted tree. This requires the items to be comparable, and it increases the add and remove complexity to logarithmic (keeping constant time for checking). But while this supports access of the i-th item in logarithmic time, which item is the i-th one will vary, and there is really no big demand for this functionality.
The clincher is that C++11 requires O(1) average time for inserts in an unordered container, which is incompatible with the ordered tree.
So, since direct indexing is impractical (linear time) and not in demand, it's not offered, but you can always use *std::next( s.begin(), i )
as a linear time alternative to a hypothetical s[i]
. In principle you can optimize that for a set that doesn't change, by copying it to a std::vector
. But in most cases it will be better to use iterators.