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

Mr.*_*Boy 9 c++ templates stl function c++14

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());
Run Code Online (Sandbox Code Playgroud)

But I cannot figure out the function signature.

void my_func(??? i1, ??? i2)
{
  std::for_each(i1, i2, ...); // dumb example implementation
}
Run Code Online (Sandbox Code Playgroud)

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?

Nat*_*ica 13

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
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

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
};
Run Code Online (Sandbox Code Playgroud)


JeJ*_*eJo 8

You could write a templated function

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

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);
}
Run Code Online (Sandbox Code Playgroud)


Bat*_*eba 7

The syntax is not too obscure! The following way uses the range for at the point of use:

template <template<typename...> class Iterable, typename T>
void foo(
    const Iterable<T>& y // the container
){
    for (auto&& e : y){
        // e is the 'thingy' in the container.
    }
}
Run Code Online (Sandbox Code Playgroud)

and you can pass any iterable container of arbitrary type to foo.

  • 一种有趣的方法来抽象甚至迭代器,尽管不确定这是否是OP所称的“简单”(模板模板参数是最容易遇到的事情) (3认同)
  • @ formerlyknownas_463035818:但这真是美!也许此答案不一定针对OP:答案不一定非要如此。 (2认同)
  • @Bathsheba我担心的是,我仅凭一个模板参数就不了解此解决方案的好处。[示例](https://godbolt.org/z/V89f7A)。 (2认同)