I am currently doing some exercises with templated functions. I had the task to write a implementation of the transform algorithm. I did it like the following and it works:
template <class in, class out, class T>
out stransform(in b, in e, out d, T p(const T&)) {
while (b != e)
*d++ = p(*b++);
return d;
}
As with the normal transform I have to call the predicate with an explicit type like
stransform(begin(vec1), end(vec1), back_inserter(vec2), predi<double>);
Now, I stumbled upon the C++11 Lambdas and wanted to call my function like this:
stransform(begin(vec1), end(vec1), back_inserter(vec2), [] (double x) ->double {return x * 10;} );
With that I do get a compiler error that the type cant be deduced. This is the thing I dont understand as I am defining the T type in my lambda actually twice.
I did also check back the original transform function, with which it is working. I then checked the implementation of that one and it is obviously implemented with a template class for the whole function. Is that the correct way for implementing predicates with templates?
The predicate is normally a simple template argument:
template <class in, class out, class UnaryPredicate>
out stransform(in b, in e, out d, UnaryPredicate p);
This will accept pointers to function, lambdas and function objects.
T p(const T&)
is the type of a function which takes a T
by reference. Your lambda takes its argument by value.
stransform (
begin (vec1),
end (vec1),
back_inserter (vec2),
[] (const double & x) -> double {
return x * 10;
});
This should work. A lambda which does not perform any capturing is convertible to an ordinary function.
it is obviously implemented with a template class for the whole function
Slight aside for proper terminology: std::transform
is a function template, not a function. More importantly, in a declaration of the style
template<class InputIterator, class OutputIterator, class Functor>
OutputIterator
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f);
the template parameters InputIterator
, OutputIterator
and Functor
are not required to be class types. Consider this example:
// function declaration
int increment(int);
int array[] = { 0, 1, 2, 3, 4 };
transform(std::begin(array), std::end(array), std::begin(array), increment);
Then InputIterator
and OutputIterator
are deduced to be int*
and Functor
is int(*)(int)
, none of which is a class type -- much less a template class, but I digress. And in fact, transform
could just as well be declared
template<typename InputIterator, typename OutputIterator, typename Functor>
OutputIterator
transform(InputIterator begin, InputIterator end, OutputIterator out, Functor f);
where the keyword typename
is a bit more clear on the nature of the template parameters: they're types, of any nature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With