I'm using std::set
to store unique instances of a class. std::set
does not have an overloaded subscript operator so you can't do set[0]
for example.
I found a way to do it:
auto myClass = *std::next(set.begin(), index);
However, I found it monotonous to copy that code over and over again. So I decided it would be much more convenient to just extend std::set
(class sset
) and just overload the subscript operator in it.
template <class T>
class sset: public std::set<T>
{
public:
T operator[](const uint32_t i) const
{
if(i <= (this->size()-1))
return *std::next(this->begin(), i);
else
throw std::out_of_range("Index is out of range");
}
};
int main()
{
auto myClass = set[0]; //works and no exception thrown
return 0;
}
I achieved the desired behavior but it occurred to me that there must have been a reason the standard didn't include a subscript operator. Surely not just laziness.
Is there any preceived disadvantage or possible future problems one can see doing this?
Indexing should never be more than logarithmic time, that's what's expected. This indexing is (at least) linear time. That's awfully inefficient. If you run through all items in a set, using that indexing, you get quadratic total time. That's a good reason to not do it.
For the code shown, note that
if(i <= (this->size()-1)
doesn't handle size 0 well. In this case you get unsigned wrap-around so that the condition is true
. Dereferencing the end iterator is then Undefined Behavior.