简体   繁体   English

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

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

I am trying to write an overload function for both double and vector<double> .我正在尝试为doublevector<double>编写重载 function 。

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编译器无法解析重载degrees function,一直报错

couldn't deduce template parameter '_UnaryOperation'

Edit: fix the part with reserve , it is an obvious mistake.编辑:用reserve修复部分,这是一个明显的错误。

You need to specify which overload should be passed to std::transform .您需要指定应将哪个重载传递给std::transform Eg例如

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

BTW: std::vector<double> out(val.size());顺便说一句: std::vector<double> out(val.size()); would construct out as containing val.size() elements with value 0.0 . out构造为包含值为0.0val.size()元素。 I suppose this is not what you want.我想这不是你想要的。 Default-initialization and reserve would be fine.默认初始化和reserve就可以了。

There are mainly two issues主要有两个问题

  1. There are two functions overloads from which compiler can not choose it automatically, which one to use.有两个函数重载编译器无法自动选择它,使用哪一个。 So you need to explicitly specify which one is to pass to the std::transform .因此,您需要明确指定将哪一个传递给std::transform

  2. The std::vector<double> out(val.size()); std::vector<double> out(val.size()); will create a vector of double with size val.size() and all the elements will be initiated with 0.0 .将创建一个大小val.size()的 double 向量,所有元素都将以0.0启动。 The std::back_inserter(out) then add element after these. std::back_inserter(out)然后在这些之后添加元素。 Presumably, you do not want to have val.size() number of 0.0 s in the out vector, prior to the actual elements.据推测,您不希望在实际元素之前在out向量中有val.size()数量为0.0 s。 You need a std::vector::reserve there, for unwanted real locations.对于不需要的真实位置,您需要一个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: 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;
}

See a Demo查看演示

You cannot pass an overload set around, but you can pass a functor with overloaded call operator:你不能传递一个重载集,但你可以传递一个带有重载调用运算符的函子:

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

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

How is it possible, in this call怎么可能,在这个电话里

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

that degrees is not known?那个degrees不知道? 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 ?我的意思是, std::transform应该尝试对val中的每个元素应用degrees ,并且由于这些元素中的每一个都是double ,因此 transform 应该利用第一个重载,即采用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, ie 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 ).然而,尽管这种动机可能令人信服,但它需要编译器将决定应该调用什么degrees的决定延迟到实际调用的那一刻,即不是在std::transform的调用站点,而是std::transform (特别是在 cppreference 文档页面上的这个可能的实现中评估表达式unary_op(*first1++)时)。

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

One way around is to wrap degrees in a function object with overloaded operator() , as suggested by 463035818_is_not_a_number ;一种解决方法是在 function object 中使用重载的operator()包装degrees ,如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() .这样做, object degrees将在std::transform调用站点知道,并且仅std::transform内部,在对象的operator()的调用站点,编译器必须在operator()的重载之间进行选择。

暂无
暂无

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

相关问题 的std ::线程 <unresolved overloaded function type> 错误 - std::thread <unresolved overloaded function type> error std :: function中带有静态函数的“未解析的重载函数类型” - “unresolved overloaded function type” with static function in std::function 没有用于调用std :: transform,未解析的重载函数类型的匹配函数 - No matching function for call to std::transform, unresolved overloaded function type std :: thread :: thread( <unresolved overloaded function type> )在Qt中 - std::thread::thread(<unresolved overloaded function type>) in Qt 重载的电话*** <unresolved overloaded function type> )&#39;不明确 - call of overloaded *** <unresolved overloaded function type>)' is ambiguous 未解决的重载函数类型错误 - unresolved overloaded function type error gcc中未解决的重载函数类型 - Unresolved overloaded function type in gcc 没有匹配的函数来调用&#39;std :: list <int, std::allocator<int> &gt; :: sort( <unresolved overloaded function type> )&#39; - No matching function for call to 'std::list<int, std::allocator<int> >::sort(<unresolved overloaded function type>)' “没有匹配函数来调用'async(std :: launch,<unresolved overloaded function type>,std :: string&)'” - “no matching function for call to ‘async(std::launch, <unresolved overloaded function type>, std::string&)’” C++ 多线程错误:没有匹配的 function 调用 'std::thread::thread(<unresolved overloaded function type></unresolved> - C++ Multithreading Error : no matching function for call to 'std::thread::thread(<unresolved overloaded function type>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM