Reputation: 69
g++ generates errors for this code. I have to change std::sin
to (double (*)(double))std::sin
. Why?
#include <iostream>
#include <list>
#include <algorithm>
#include <cmath>
int main(int argc, char *argv[])
{
std::list<double> radians = {0.0, 3.14/2, 3.14};
std::list<double> sines(radians.size());
std::transform(radians.begin(), radians.end(), sines.begin(), std::sin);
for(auto i = radians.begin(), j = sines.begin(); i != radians.end(); i++, j++)
std::cout << "Angle and sine: " << *i << " " << *j << std::endl;
return 0;
}
Upvotes: 1
Views: 78
Reputation: 172924
Because std::transform
is function template, the type of function object parameter is declared as template parameter which needs to be deduced from the function argument. But std::sin
has several overloads, there's no context to determine which overload should be selected and then to be used to deduce the template argument.
You can use static_cast
(or c-style cast as you showed) to specify one.
static_cast
may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type, as instd::for_each(files.begin(), files.end(), static_cast<std::ostream&(*)(std::ostream&)>(std::flush));
e.g.
std::transform(radians.begin(), radians.end(), sines.begin(), static_cast<double(*)(double)>(std::sin));
Or specify the template argument explicitly to bypass the template argument deduction. With the known function parameter type overload resolution would be performed to select the proper overload.
std::transform<std::list<double>::iterator,
std::list<double>::iterator,
double(*)(double)
>(radians.begin(),
radians.end(),
sines.begin(),
std::sin
);
Upvotes: 6
Reputation: 303
So writed. You can use ...
using namespace std;
double sinn(double i){
return sin(i);
}
this function instead of sin.
Upvotes: -1
Reputation: 12759
Given your use case, another way to disambiguate the function overloads is to write a lambda accempting a specific type:
std::list<double> radians = {0.0, 3.14/2, 3.14};
std::list<double> sines;
std::transform(radians.begin(), radians.end(),
std::back_inserter(sines),
[] (double x) { return std::sin(x); });
// ^^^^^^
Edit
As noted by walnut, since C++14, we can use auto
and let the compiler deduce the value type from the iterators.
std::transform(radians.begin(), radians.end(),
std::back_inserter(sines),
[] (auto x) { return std::sin(x); });
Upvotes: 2