g++ 为 transform() 的参数生成错误
g++ generates errors for an argument of transform()
g++ 为此代码生成错误。我必须将 std::sin
更改为 (double (*)(double))std::sin
。为什么?
#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;
}
因为 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
有几个重载,所以没有上下文来确定应该 selected 哪个重载然后用于推导模板参数。
您可以使用 static_cast
(或您展示的 c 样式转换)来指定一个。
static_cast
may also be used to disambiguate function overloads by
performing a function-to-pointer conversion to specific type, as in
std::for_each(files.begin(), files.end(),
static_cast<std::ostream&(*)(std::ostream&)>(std::flush));
例如
std::transform(radians.begin(), radians.end(), sines.begin(), static_cast<double(*)(double)>(std::sin));
或者显式指定模板参数以绕过模板参数推导。使用已知的函数参数类型重载解析将执行 select 正确的重载。
std::transform<std::list<double>::iterator,
std::list<double>::iterator,
double(*)(double)
>(radians.begin(),
radians.end(),
sines.begin(),
std::sin
);
根据您的用例,消除函数重载歧义的另一种方法是编写接受特定类型的 lambda:
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); });
// ^^^^^^
编辑
如 walnut 所述,自 C++14 起,我们可以使用 auto
并让编译器从迭代器推导出值类型。
std::transform(radians.begin(), radians.end(),
std::back_inserter(sines),
[] (auto x) { return std::sin(x); });
这么写的。
您可以使用
...
using namespace std;
double sinn(double i){
return sin(i);
}
这个函数代替了sin。
g++ 为此代码生成错误。我必须将 std::sin
更改为 (double (*)(double))std::sin
。为什么?
#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;
}
因为 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
有几个重载,所以没有上下文来确定应该 selected 哪个重载然后用于推导模板参数。
您可以使用 static_cast
(或您展示的 c 样式转换)来指定一个。
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));
例如
std::transform(radians.begin(), radians.end(), sines.begin(), static_cast<double(*)(double)>(std::sin));
或者显式指定模板参数以绕过模板参数推导。使用已知的函数参数类型重载解析将执行 select 正确的重载。
std::transform<std::list<double>::iterator,
std::list<double>::iterator,
double(*)(double)
>(radians.begin(),
radians.end(),
sines.begin(),
std::sin
);
根据您的用例,消除函数重载歧义的另一种方法是编写接受特定类型的 lambda:
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); });
// ^^^^^^
编辑
如 walnut 所述,自 C++14 起,我们可以使用 auto
并让编译器从迭代器推导出值类型。
std::transform(radians.begin(), radians.end(),
std::back_inserter(sines),
[] (auto x) { return std::sin(x); });
这么写的。 您可以使用 ...
using namespace std;
double sinn(double i){
return sin(i);
}
这个函数代替了sin。