Reputation: 16777
I am trying to write a higher-order function which would wrap around the standard library functions taking input and output iterators. Here's a failed attempt:
#include <algorithm>
#include <iostream>
#include <type_traits>
#include <vector>
using namespace std;
template <template <typename, typename> class Func, typename InpIt, typename UnaryFunction>
decltype(Func<InpIt, UnaryFunction>(declval<InpIt>(), declval<InpIt>(), declval<UnaryFunction>())) Apply(InpIt first, InpIt last, UnaryFunction f)
{
return Func<InpIt, UnaryFunction>(first, last, f);
}
int main()
{
vector<int> a(5);
Apply<for_each>(a.begin(),
a.end(),
[](int i)
{
cout << i << endl;
});
return 0;
}
Clang 3.5 fails with
high.cpp:16:3: error: no matching function for call to 'Apply'
Apply<for_each>(a.begin(),
^~~~~~~~~~~~~~~
high.cpp:8:100: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Func'
decltype(Func<InpIt, UnaryFunction>(declval<InpIt>(), declval<InpIt>(), declval<UnaryFunction>())) Apply(InpIt first, InpIt last, UnaryFunction f)
What is the right way to express this? Also, what I would ideally want is to be able to simply say something like
template <MagicIncantation Func, typename Range, typename ... Args>
MoreMagic Apply(Range&& rng, Args&& ... args)
{
using std::begin; using std::end;
Func(begin(rng), end(rng), args...);
}
allowing one to avoid specifying iterators when you want to iterate over the full range.
Upvotes: 4
Views: 404
Reputation: 2953
You can use a wrapper class as seen here:
template <template <typename, typename> class Func, typename InpIt, typename UnaryFunction>
UnaryFunction Apply(InpIt first, InpIt last, UnaryFunction f)
{
return Func<InpIt, UnaryFunction>::f(first, last, f);
}
template<typename T, typename T2>
struct for_each_wrapper
{
static T2 f(T ta, T tb, T2 t2)
{
return std::for_each(ta, tb, t2);
}
};
int main()
{
vector<int> a(5);
Apply<for_each_wrapper>(
a.begin(),
a.end(),
[](int i)
{
std::cout << i << endl;
});
return 0;
}
Upvotes: 1
Reputation: 63154
You'll find useful information in this question/answer, but what comes out of it is that you can't pass function templates as template (template) parameters, so passing std::for_each
that way is not possible.
Upvotes: 2