I\'m trying to write a projection function that could transform a vector
into a vector
. Here is an example:
auto v =
Basic decltype()
usage:
template
auto select(const std::vector& c, F f)
-> std::vector
{
using R = decltype(f(c[0]));
std::vector v;
std::transform(std::begin(c), std::end(c), std::back_inserter(v), f);
return v;
}
Basic std::result_of
usage:
template ::type>
std::vector select(const std::vector& c, F f)
{
std::vector v;
std::transform(std::begin(c), std::end(c), std::back_inserter(v), f);
return v;
}
Advanced decltype()
usage and perfect-forwarding (see notes*):
template
auto select(const std::vector& c, F&& f)
-> std::vector::type&>()(*c.begin()))>::type>
{
using R = typename std::decay::type&>()(*c.begin()))>::type;
std::vector v;
std::transform(std::begin(c), std::end(c)
, std::back_inserter(v)
, std::forward(f));
return v;
}
Advanced std::result_of
usage and perfect-forwarding (see notes*):
template ::type&(typename std::vector::const_reference)>::type>::type>
std::vector select(const std::vector& c, F&& f)
{
std::vector v;
std::transform(std::begin(c), std::end(c)
, std::back_inserter(v)
, std::forward(f));
return v;
}
* Note: Options #3 and #4 assume that the std::transform
algorithm takes a function object by-value, and then uses it as a non-const lvalue. This is why one can see this strange typename std::decay
syntax. If the function object is supposed to be called within the select
function itself, and the result type is not going to be used as a container's template argument (for the purpose of what the outer-most std::decay
is used), then the correct and portable syntax for obtaining the return type is:
/*#3*/ using R = decltype(std::forward(f)(*c.begin()));
/*#4*/ typename R = typename std::result_of::const_reference)>::type