Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-template function that processes any container of elements of specific type

I'd like to have a function as described in title.

I've noticed that STL algorithms that work with containers of any type (list, vector, etc) containing elements of any type (int, double) provide genericity by using iterator types as template parameters, e.g.

template<typename _II, typename _OI>
inline _OI
copy(_II __first, _II __last, _OI __result)

This is a good method until the algorithm works for any type of elements. The only requirement for element type is that it must have copy constructor.

But suppose we have one concrete type

class MyElement
{
    public:
    void doSomethingWithElement();
};

and we want to implement a function that processes number of elements of this type by calling function doSomethingWithElement().

Writing a function that receives container of specific type is not very convenient because many containers are treated in the same way (e.g. iterators), and if there will be need for processing containers of different types we'll be forced to duplicate the code. Writing a template works fine, but it seems ugly because we have to implement function in place where it is declared (in header file). Also, when we want to process elements of only one type, parametrizing this type is not the right way to achieve the goal.

I've been thinking about iterator interface that could be used like

void processContainer(IIterator<MyElement> begin, IIterator<MyElement> end);

If this iterator had pure virtual operator++ and operator* that were implemented in derived classes, we could pass such objects to processContainer. But there is a problem: if IIterator is abstract class, we can't instantiate it in the implementation of processContainer, and if we pass a pointer to IIterator, this function will be able to modify it.

Does anybody know any other hack to do this? Or would be another approach better than these ones above? Thanks in advance.

like image 507
Oleg Andriyanov Avatar asked Sep 15 '25 07:09

Oleg Andriyanov


1 Answers

The simpler approach is to ignore the restriction and just implement your function as a template for any iterator. If the iterator does not refer to the type, then the user will get a horrible error message in the lines of "type X does not have doSomethingWithElement member function`.

The next thing would be to provide a static_assert, the function would still take any iterator (meaning that it will participate in overload resolution for any type) but the error message will be slightly more informative.

Furthermore you can decide to use SFINAE to remove the overload from the set of candidates. But while SFINAE is a beautiful golden hammer, I am not sure that you have the appropriate nail at hand.

If you really want to go further down the lane, you can take a look at any_iterator in the Adobe libraries as an example on how to perform type erasure on the iterator type to avoid the template. The complexity of this approach is orders of magnitude higher than any of the previous, and the runtime cost will also be higher, providing the only advantage of a cleaner ABI and less code size (different iterators can be passed to a single function).

like image 166
David Rodríguez - dribeas Avatar answered Sep 16 '25 22:09

David Rodríguez - dribeas