No find member in std::vector - c++

Is there any particular reason why std::vector does not have a member function find? Instead you have to call std::find (and #include <algorithm>).
The reason why I ask is that I think it would be a good thing to be able to change container class in some piece of implementation without having to change the code wherever the container is accessed. Say I replace an std::vector where the implementation uses std::find with an std::map. Then I also have to replace the call of std::find with a call to the member find, unless I want to keep the linear complexity of std::find. Why not just have a member find for all container classes, which finds an element with whatever algorithm is best suited for each container?

Conceptually, std::find only requires two InputIterators to work and not an std::vector. As such, one implementation works for all containers including STL containers, and standard arrays, and anything that can supply an InputIterator, including for example an istream_iterator() - nice!
So, instead of providing one find() method for every container (and take into account that for some it might not possible, like standard arrays), one single, generic find() function is provided for all. This likely makes your code more resilient to change than adding a find() method for each container since it provides a consistent interface to search in any collection: an input stream from console, network etc., or just a basic array. This is an important aspect of the STL generic design philosophy: you can search for elements in any collection/range defined by two InputIterators.
The downside, as you note, is that in some cases, better performance may be achieved using the container's own method, which can make special assumptions to improve performance (similarly for list::remove, unorderd_map::remove/find() etc.). For this reason, containers can provide (and this is a well known design feature of STL) a method specifically for performance reasons: for example a std::unordered_map does not require one to iterate through the entire map to find an element.
In summary, since the generic std::find works efficiently for a vector, there is no need to provide a member function, since it might enforce even less portable design.
For all things STL related see The C++ Standard Library - A Tutorial and Reference, 2nd Edition

std::find is a common solution. some classes need some kind of specialization of this function so that's why they have them locally (as i remember Meyers said that if a class has its own function-member then you should use it instead of globally defined)

Related

Specialize std::copy for custom iterators

From what I understand one can write template specializations for function template in the std namespace. I have written a CircularBuffer<T> class and implemented a random access iterator for this class. As is the std::copy() algorithm works with my custom iterators but it is not optimal. It iterates through the range and copies elements one by one. I could write a more optimal implementation for trivially copiable types by using std::memcpy() on internal pointers.
My question is that even possible? I know how I would create an overload of std::copy() as a template with output iterator being the template parameter. But that cannot be done since you can only write template specializations of function templates in the std namespace. Any help in pointing me in the right direction would be helpful. From what I could gather through Google, this can't be done, but I would love to be proven wrong :)
Maybe your question should be: should I do it ?
Users who make use of your class should already be aware of what std::copy is and how it works and inherently the performance implications. So providing a specialization could make matters worse. std::copy guarantees that N assignments are made; according to the standard:
Exactly (last - first) assignments
Also, it is not uncommon that when std::copy is used, it is also used with back_inserters or other manipulators, that will probably not play well with optimization.
However, you could, for instance, choose to provide a direct access to the buffer like in std::vector::data.
My question is that even possible?
One way around this issue that you seem to have is to export this knowledge - in a sense - to the users of your class. Just add an extra level of indirection. So instead of having iterators to the elements directly you will return iterators to the blocks of memory. Then you will be able to have Contiguous iterators.
https://en.cppreference.com/w/cpp/named_req/ContiguousIterator

RangeV3: why not specialize algorithm for specific containers?

The "old" STL does not allow say std::find to be specialized to use the member functions for std::set or std::unordered_map, etc. It cannot, since the former use iterators, the latter need the containers, and from iterators there are no means to get the containers. There is even a question about that (Specializing STL algorithms so they automatically call efficient container member functions when available).
Since Range V3 finally moves the focus from iterators to ranges, one could expect that finally std::find would be specialized automatically for std::set, which in turn makes std::none_of_equal (if it were adopted) do what you'd like, etc.
However, reading its currently implementation, I see no provision for such a feature. Why?

per-container optimizations for functions that operate on iterators

So I know the point of iterators is to abstract the underlying container so you don't have to worry about what it is.
But say you wanted to write an optimized version of merge sort and wanted to do an in place sort if the underlying container was a linked list, since you can run merge sort in-place on a linked list without the need for extra container allocations.
Is there any way to get this information to know whether you're operating on a linked structure and/or access the pointers for Standard Library and other containers?
I'm assuming there is a way since that is what std::sort does? How?
I have also always wished for a way to do this, but the answer is kind-of, but not really. This isn't possible in general, because of the template deduction rules.
Each iterator may be a member of a class, but since multiple classes may have the same iterators, if a function receives these iterators, it is literally and theoretically impossible to deduce which container it came from. That hinders things somewhat.
If you don't need the container type and can work with the iterator type alone, then yes, std::sort could optimize based on the underlying container. But no, std::sort doesn't have a special algorithm for node based containers in any C++ standard library that I know of.
The containers themselves sometimes have specialized versions, see std::list<T>::sort, but the generic std::sort can't make use of that since it works on any arbitrary range, and std::list<T>::sort only works on the entire container.
I really wish they would. Also a specialization of std::lower_bound and similar when called on the tree-based containers would be awesome.
A library implementor can do a certain set of things that are not portable and depend on the details of the implementation. While in the standard the iterator types are referred as nested types in the container, nested types are not deducible, the implementation can decide to implement those as types with namespace scope, which are deducible, and provide a nested typedef. The implementation could then, within the limits of the requirements placed in the standard, optimize the operations.
I don't know of any implementation that implements std::sort as merge sort for lists, but there are other tricks that are used in implementations, for example std::copy when the iterators are into vectors holding POD types is implemented in some libraries by calling std::memmove rather than copying one element at a time.
As I mentioned before, while this can be done by the implementor, writing your own code attempting to do the same would be non-portable and brittle, as it would depend on details of one implementation that might change in the next version of the library or even by changing compiler flags.

Specializing STL algorithms so they automatically call efficient container member functions when available

The STL has global algorithms that can operate on arbitrary containers as long as they support the basic requirements of that algorithm. For example, some algorithms may require a container to have random access iterators like a vector rather than a list.
When a container has a faster way of doing something than the generic algorithm would, it provides a member function with the same name to achieve the same goal - like a list providing its own remove_if() since it can remove elements by just doing pointer operations in constant time.
My question is - is it possible/advisable to specialize the generic algorithms so they automatically call the member function version for containers where it's more efficient? E.g. have std::remove_if call list::remove_if internally for lists. Is this already done in the STL?
Not in the case of remove_if, since the semantics are different. std::remove_if doesn't actually erase anything from the container, whereas list::remove_if does, so you definitely don't want the former calling the latter.
Neither you nor the implementation can literally specialize the generic algorithms for containers because the algorithms are function templates that take iterators, and the containers are themselves class templates, whose iterator type depends on the template parameter. So in order to specialize std::remove_if generically for list<T>::iterator you would need a partial specialization of remove_if, and there ain't no such thing as a partial specialization of a function template.
I can't remember whether implementations are allowed to overload algorithms for particular iterator types, but even if not the "official" algorithm can call a function that could be overloaded, or it can use a class that could be partially specialized. Unfortunately none of these techniques help you if you've written your own container, and have spotted a way to make a standard algorithm especially efficient for it.
Suppose for example you have a container with a random-access iterator, but where you have an especially efficient sort technique that works with the standard ordering: a bucket sort, perhaps. Then you might think of putting a free function template <typename T> void sort(MyContainer<T>::iterator first, MyContainer<T>::iterator last) in the same namespace as the class, and allow people to call it with using std::sort; sort(it1, it2); instead std::sort(it1, it2);. The problem is that if they do that in generic code, they risk that someone else writing some other container type will have a function named sort that doesn't even sort the range (the English word "sort" has more than one meaning, after all). So basically you cannot generically sort an iterator range in a way that picks up on efficiencies for user-defined containers.
When the difference in the code depends only on the category of the iterator (for example std::distance which is fast for random access iterators and slow otherwise), this is done using something called "iterator tag dispatch", and that's the most common case where there's a clear efficiency difference between different containers.
If there are any remaining cases that apply to standard containers (discounting ones where the result is different or where the efficiency only requires a particular iterator category), let's have them.
It is not possible - the algorithms work with iterators, and iterators have no knowledge of the container object they refer to. Even if they did, there would be no way to determine at compile time whether a given iterator range refers to the whole of a container, so it could not be done by specialisation alone; there would need to be an extra runtime check.
The only way to do this would be to create your own wrapper templates for each of the algorithms, taking a container rather than a pair of iterators. Then you could specialize your wrapper for each container type that could be optimized. Unfortunately this removes a lot of the flexibility of the standard algorithms, and litters your programs with a bunch of non-standard calls.
What you are looking for isn't specialization, but overloading. You could provide alternative versions of the algorithms (not, legally, in namespace std, though) that take containers as arguments, rather than iterator pairs, and either call the STL pendants calling begin() and end() on the container, or do something else. Such an approach of course does require the code to call your functions instead of the STL functions, though.
This has certainly been done before, so you might actually find a set of headers out there saving you the work to write all this boilerplate code.

Is it a good idea to create an STL iterator which is noncopyable?

Most of the time, STL iterators are CopyConstructable, because several STL algorithms require this to improve performance, such as std::sort.
However, I've been working on a pet project to wrap the FindXFile API (previously asked about), but the problem is it's impossible to implement a copyable iterator around this API. A find handle cannot be duplicated by any means -- DuplicateHandle specifically forbids passing these types of handles to it. And if you just maintain a reference count to the find handle, then a single increment by any copy results in an increment of all copies -- clearly that is not what a copy constructed iterator is supposed to do.
Since I can't satisfy the traditional copy constructible requirement for iterators here, is it even worth trying to create an "STL style" iterator? On one hand, creating some other enumeration method is going to not fall into normal STL conventions, but on the other, following STL conventions are going to confuse users of this iterator if they try to CopyConstruct it later.
Which is the lesser of two evils?
An input iterator which is not a forward iterator is copyable, but you can only "use" one of the copies: incrementing any of them invalidates the others (dereferencing one of them does not invalidate the others). This allows it to be passed to algorithms, but the algorithm must complete with a single pass. You can tell which algorithms are OK by checking their requirements - for example copy requires only an InputIterator, whereas adjacent_find requires a ForwardIterator (first one I found).
It sounds to me as though this describes your situation. Just copy the handle (or something which refcounts the handle), without duplicating it.
The user has to understand that it's only an InputIterator, but in practice this isn't a big deal. istream_iterator is the same, and for the same reason.
With the benefit of C++11 hindsight, it would almost have made sense to require InputIterators to be movable but not to require them to be copyable, since duplicates have limited use anyway. But that's "limited use", not "no use", and anyway it's too late now to remove functionality from InputIterator, considering how much code relies on the existing definition.