There is a wide range of algorithms to find/modify/replace data in containers.
Let's say you have a set of ints, doing what you want is the following:
std::set<int> blah;
// ... some stuff happens ...
if (blah.find(123) != blah.end())
{
// ...
}
Now, you're saying, "but my container doesn't have find!". Not a problem, you can use std::find!
std::vector<int> v;
// ... some stuff happens ...
if (std::find(v.begin(), v.end(), 123) != v.end())
{
// ...
}
Note that v can be ANYTHING, as long it supports forward iterators (which all containers do).
Now you're saying, "but it's not very efficient! The complexity of find is O(n)!"
True, true. If your container is sorted, you should use binary search O(log n):
if (std::binary_search(v.begin(), v.end(), 123))
{
// ...
}
What's great about this is that it works on any container, provided it's sorted.
Then, what you can do is write a metafunction that will call the member function find() when it exists or use std::find() when there's none. This will automatically, and at compile time, use the most efficient way to check for the existence of an entry.
I am not talking about how I end up searching the container. I am talking about the syntax. Besides, how a container is searched should be abstracted away in the container's implementation and the algorithm should be documented.
Compare this syntax:
> if (std::find(v.begin(), v.end(), 123) != v.end())
To
> if (123 in v)
If in is an operator and overloaded by std::vector, then it's easy to implement.
> If in is an operator and overloaded by std::vector, then it's easy to implement.
However, searching a `std::vector` is not really part of its implementation. So, requiring every single range to overload an operator for trivial searching is not good, especially since there are only a few containers that have non-trivial searching.
Instead, the range-based find could be specialized for containers that have non-trivial searching instead(perhaps it calls a `.find` method if available otherwise it does trivial searching).
In [Linq](http://pfultz2.github.io/Linq/), the find is specialized for mapped containers and for strings(it doesn't check for a `.find` method since that can't be done on msvc). So you can search a `std::vector` like this:
std::vector<int> v = { ... };
auto it = v | linq::find(123);
And you can also search the keys of a map like this:
std::map<int, std::string> m = { ... };
auto it = m | linq::find(123);
Plus, it has a contains function, so you can do this:
if (v | linq::contains(123))
Or this:
if (m | linq::contains(123))
There really is no need for a new operator just for this, since a function will suffice. However, if you really inclined to this, you could always write your own [named operator](https://github.com/klmr/named-operator)(although I don't know if it would become standard):
I hate to do this, but I think you totally misunderstood the point of the STL.
The fact that algorithms are separated from containers is a major feature of the STL and one of the major reasons why it is so awesome.
By having algorithms separated from containers you implement algorithms only once and only have to give your container the right properties to use (an) algorithm(s).
You reduce coupling and the chances for errors and bugs. When you need to switch to a different containers, you don't have to rewrite your code. You can also try different algorithms easily.
> if (123 in v)
I'm sorry but C++ is about describing precisely what you want to do and how you want it to be done to get the maximum performance out of your machine.
What is "in"? What does it do? How does it allocate memory? How can I get the position of the entry? Which algorithm is used to search for the entry? What must I do to support "in"?
On the other side,
> if (std::find(v.begin(), v.end(), 123) != v.end())
I use a O(n) algorithm to search from the beginning to the end of the container for an entry equal to 123.
There is a wide range of algorithms to find/modify/replace data in containers.
Let's say you have a set of ints, doing what you want is the following:
Now, you're saying, "but my container doesn't have find!". Not a problem, you can use std::find! Note that v can be ANYTHING, as long it supports forward iterators (which all containers do).Now you're saying, "but it's not very efficient! The complexity of find is O(n)!"
True, true. If your container is sorted, you should use binary search O(log n):
What's great about this is that it works on any container, provided it's sorted.Then, what you can do is write a metafunction that will call the member function find() when it exists or use std::find() when there's none. This will automatically, and at compile time, use the most efficient way to check for the existence of an entry.