I am trying to write an overload function for both double
and vector<double>
.
I just did the following:
constexpr double degrees(double val) { return v * M_1_PI * 180.0; }
std::vector<double> degrees(const std::vector<double>& val)
{
std::vector<double> out;
out.reserve(val.size());
std::transform(val.begin(), val.end(), std::back_inserter(out), degrees);
return out;
}
I expect this to be rather straightforward, but it does not compile, and I cannot figure it out. The compiler cannot resolve the overloaded degrees
function, and keeps complaining
couldn't deduce template parameter '_UnaryOperation'
Edit: fix the part with reserve
, it is an obvious mistake.
I don't want to believe that the asker didn't know they are defining two functions with the same name degrees
, so I'll give another shade to my answer.
How is it possible, in this call
std::transform(val.begin(), val.end(), std::back_inserter(out), degrees);
that degrees
is not known? I mean, std::transform
should try to apply degrees
to each element in val
, and since each of those elements is a double
, isn't it obvious that transform should make use of the first overload, the one which takes a double
?
As convincing as this motivation might be, though, it would require the compiler to delay/defer the decision of what degrees
should be called to the moment it's actually called, i.e. not at the call site of std::transform
, but inside std::transform
(specifically, when evaluating the expression unary_op(*first1++)
in this possible implementation on the cppreference doc page).
This is simply not possible, as the rules are that the compiler must know at the call site of a function what its arguments are. With reference to the example, at the call site of std::transform
the compiler has no idea which of the overloads of degree
is needed.
One way around is to wrap degrees
in a function object with overloaded operator()
, as suggested by 463035818_is_not_a_number; doing so, the object degrees
would be known at std::transform
call site, and only inside std::transform
, at the call site of the object's operator()
would the compiler have to choose between the overloads of operator()
.