[英]Unresolved overloaded function type in std::transfrom
I am trying to write an overload function for both double
and vector<double>
.我正在尝试为
double
和vector<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.0
的val.size()
元素。 I suppose this is not what you want.我想这不是你想要的。 Default-initialization and
reserve
would be fine.默认初始化和
reserve
就可以了。
There are mainly two issues主要有两个问题
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
。
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;
}
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.