繁体   English   中英

std::transfrom 中未解决的重载 function 类型

[英]Unresolved overloaded function type in std::transfrom

我正在尝试为doublevector<double>编写重载 function 。

我刚刚做了以下事情:


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

我希望这是相当简单的,但它不能编译,我无法弄清楚。 编译器无法解析重载degrees function,一直报错

couldn't deduce template parameter '_UnaryOperation'

编辑:用reserve修复部分,这是一个明显的错误。

您需要指定应将哪个重载传递给std::transform 例如

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), static_cast<double(*)(double)>(degrees));
    //                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    return out;
}

顺便说一句: std::vector<double> out(val.size()); out构造为包含值为0.0val.size()元素。 我想这不是你想要的。 默认初始化和reserve就可以了。

主要有两个问题

  1. 有两个函数重载编译器无法自动选择它,使用哪一个。 因此,您需要明确指定将哪一个传递给std::transform

  2. std::vector<double> out(val.size()); 将创建一个大小val.size()的 double 向量,所有元素都将以0.0启动。 std::back_inserter(out)然后在这些之后添加元素。 据推测,您不希望在实际元素之前在out向量中有val.size()数量为0.0 s。 对于不需要的真实位置,您需要一个std::vector::reserve

That being said, I would suggest having a lambda function instead of a free function, which has the advantage of having the implementation of the function right into the place where it is called:

std::vector<double> degrees(const std::vector<double>& val)
{
    std::vector<double> out;
    out.reserve(val.size()); // reserve some memory
    std::transform(val.begin(), val.end(), std::back_inserter(out),
        [](double ele) {return ele * M_1_PI * 180.0; }
    );
    return out;
}

查看演示

你不能传递一个重载集,但你可以传递一个带有重载调用运算符的函子:

struct degrees {
    constexpr double operator()(double val) {return val * 0.3 * 180.0;}

    std::vector<double> operator()(const std::vector<double>& val) {
        std::vector<double> out(val.size());
        std::transform(val.begin(), val.end(), std::back_inserter(out), degrees{});
        return out;
    }
};

我不想相信提问者不知道他们定义了两个同名的函数degrees ,所以我会给我的答案另一种阴影。

怎么可能,在这个电话里

std::transform(val.begin(), val.end(), std::back_inserter(out), degrees);

那个degrees不知道? 我的意思是, std::transform应该尝试对val中的每个元素应用degrees ,并且由于这些元素中的每一个都是double ,因此 transform 应该利用第一个重载,即采用double的重载不是很明显吗?

然而,尽管这种动机可能令人信服,但它需要编译器将决定应该调用什么degrees的决定延迟到实际调用的那一刻,即不是在std::transform的调用站点,而是std::transform (特别是在 cppreference 文档页面上的这个可能的实现中评估表达式unary_op(*first1++)时)。

这根本不可能,因为规则是编译器必须在 function 的调用站点知道它的 arguments 是什么。 参考这个例子,在std::transform的调用点,编译器不知道需要哪个degree的重载。

一种解决方法是在 function object 中使用重载的operator()包装degrees ,如463035818_is_not_a_number所建议的那样; 这样做, object degrees将在std::transform调用站点知道,并且仅std::transform内部,在对象的operator()的调用站点,编译器必须在operator()的重载之间进行选择。

暂无
暂无

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

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