我有一个模板类和一个朋友operator*
函数
StereoSmp<TE> operator* (const StereoSmp<TE>& a, TE b)
我将其与TE=float
一起使用,但我需要乘以StereoSmp<float> * double
我认为这应该是可能的,因为它应该自动将double
转换为float
并且有效但我得到错误:
no match for ‘operator*’ (operand types are ‘StereoSmp<float>’ and ‘__gnu_cxx::__alloc_traits<std::allocator<double> >::value_type {aka double}’) deduced conflicting types for parameter ‘TE’ (‘float’ and ‘double’)
为什么它不会自动将double转换为float?我该怎么做才能允许类型之间的自动转换?
答案 0 :(得分:5)
不要让你的朋友成为模板。
template<class TE>
struct StereoSmp {
friend StereoSmp operator* (const StereoSmp& a, TE b) {
return multiply( a, b ); // implement here
}
};
这是模板StereoSmp
的每个类型实例的非模板朋友。它会考虑转换。
模板功能不考虑转换,它们只是进行精确的模式匹配。在C ++中,过载分辨率已经足够疯狂了。
答案 1 :(得分:3)
template<class U>
StereoSmp<TE> operator* (const StereoSmp<TE>& a, U b);
或如果适用:
StereoSmp<TE> a {/* ... */};
double b = /* ... */;
auto c = a * static_cast<float>(b);
为什么它不会自动将double转换为float?
因为模板扣除发生在之前可能的转换被考虑在内。如果您使用a*b
a
和StereoSmp<float>
一个b
致电double
,则模板替换将在float
到double
之前失败可以考虑转换,名称查找将继续,直到缺少候选人。
答案 2 :(得分:2)
虽然Yakk的回答可能是这个特定情况下的最佳答案,但我想指出您可以阻止此扣减冲突并获得预期结果(通过StereoSmp<float>
,推导TE
为{{1通过使另一个参数不适用于演绎:
float
相关阅读:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3766.html
答案 3 :(得分:0)
为什么它不能自动将double转换为float?我该怎么做才能允许类型之间的自动转换?
这不是转换问题,它是模板参数推断问题。由于声明的格式为:
StereoSmp<TE> operator* (const StereoSmp<TE>& a, TE b)
...操作数类型为StereoSmp<float>
和double
,C ++推理规则不起作用,因为它们没有考虑double
可转换为float
。这些规则由语言规范指定; 为什么他们不考虑潜在的转换的原因可能是因为&#34;它会使演绎非常复杂化,否则&#34;。规则已经够复杂了!
您当然可以将double
参数投射到float
,它会正常工作。此外,您可以使operator*
成为StereoSmp
的成员函数,或者您可以独立地参数化类型参数的类型:
template <class TE, class U> StereoSmp<TE> operator* (const StereoSmp<TE>& a, U b);