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)
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)
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
.