繁体   English   中英

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是函数模板,所以函数对象参数的类型被声明为模板参数,需要从函数参数中推导出来。 但是std::sin有几个重载,没有上下文来确定应该选择哪个重载然后用于推断模板参数。

您可以使用static_cast (或您展示的 c 样式转换)来指定一个。

static_cast也可用于通过执行函数到指针到特定类型的转换来消除函数重载的歧义,如

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));

或者明确指定模板参数以绕过模板参数推导。 使用已知的函数参数类型将执行重载解析以选择适当的重载。

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);
 }

这个功能而不是罪。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM