Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to provide the function signature for a function taking iterators of stl containers?

I want to write a function my_func that can be called as so, but does not care that v is a std::vector, it could be any STL container. A bit like std::for_each:

std::vector<std::string> v = {...};
my_func(v.begin(), v.end());

But I cannot figure out the function signature.

void my_func(??? i1, ??? i2)
{
  std::for_each(i1, i2, ...); // dumb example implementation
}

I am not great at template programming so even looking at the function declaration for std::for_each is not helping me.

Is there an easy implementation or is this fundamentally going to get messy with template vars?

like image 819
Mr. Boy Avatar asked Aug 20 '19 14:08

Mr. Boy


People also ask

Which STL function returns an iterator?

Iterators are generated by STL container member functions, such as begin() and end(). Some containers return iterators that support only the above operations, while others return iterators that can move forward and backward, be compared with <, and so on.

What are the STL iterators and what is their purpose?

An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent. Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container.


2 Answers

It depends on how generic you want the function to be. If the iterator types have to match, then

template <typename T>
void my_func(T i1, T i2)
{
    std::for_each(i1,i2,...); //dumb example implementation
}

is all you need. If you want them to be able to be different, then you just need another template parameter like

template <typename T, typename U>
void my_func(T i1, U i2)
{
    std::for_each(i1,i2,...); //dumb example implementation
}

Finally, if you don't like dealing with templates you can use a lambda instead and let the compiler take care of this for you. That would give you

auto my_func = [](auto i1, auto i2)
{
    std::for_each(i1,i2,...); //dumb example implementation
};
like image 137
NathanOliver Avatar answered Nov 06 '22 07:11

NathanOliver


You could write a templated function

template<typename Iterator>
void my_func(Iterator startIter, const Iterator endIter)
{
  std::for_each(startIter, endIter, /* lambda */);
}

In case of wondering, how to pass the third parameter of the std::for_each, you could provide one more template parameter

const auto defaultCallable = [](auto element){ }; // does nothing
template<typename Iterator, typename Callable = decltype(defaultCallable)>
void my_func(Iterator startIter, const Iterator endIter, Callable func = {})
{
    std::for_each(startIter, endIter, func);
}
like image 33
JeJo Avatar answered Nov 06 '22 05:11

JeJo