I'm heavily using std::set<int>
and often I simply need to check if such a set contains a number or not.
I'd find it natural to write:
if (myset.contains(number))
...
But because of the lack of a contains
member, I need to write the cumbersome:
if (myset.find(number) != myset.end())
..
or the not as obvious:
if (myset.count(element) > 0)
..
Is there a reason for this design decision ?
You are looking into particular case and not seeing bigger picture. As stated in documentation
std::set
meets requirement of AssociativeContainer concept. For that concept it does not make any sense to havecontains
method, as it is pretty much useless forstd::multiset
andstd::multimap
, butcount
works fine for all of them. Though methodcontains
could be added as an alias forcount
forstd::set
,std::map
and their hashed versions (likelength
forsize()
instd::string
), but looks like library creators did not see real need for it.Since c++20,
bool contains( const Key& key ) const
is available.
What about binary_search ?
I think it was probably because they were trying to make
std::set
andstd::multiset
as similar as possible. (And obviouslycount
has a perfectly sensible meaning forstd::multiset
.)Personally I think this was a mistake.
It doesn't look quite so bad if you pretend that
count
is just a misspelling ofcontains
and write the test as:It's still a shame though.
Although I don't know why
std::set
has nocontains
butcount
which only ever returns0
or1
, you can write a templatedcontains
helper function like this:And use it like this:
It lacks it because nobody added it. Nobody added it because the containers from the STL that the
std
library incorporated where designed to be minimal in interface. (Note thatstd::string
did not come from the STL in the same way).If you don't mind some strange syntax, you can fake it:
use:
Basically, you can write extension methods for most C++
std
types using this technique.It makes a lot more sense to just do this:
but I am amused by the extension method method.
The really sad thing is that writing an efficient
contains
could be faster on amultimap
ormultiset
, as they just have to find one element, whilecount
has to find each of them and count them.A multiset containing 1 billion copies of 7 (you know, in case you run out) can have a really slow
.count(7)
, but could have a very fastcontains(7)
.With the above extension method, we could make it faster for this case by using
lower_bound
, comparing toend
, and then comparing to the element. Doing that for an unordered meow as well as an ordered meow would require fancy SFINAE or container-specific overloads however.