这是一个非常简约的例子。我通过以下方式使用 Boost.Units :
#define REAL double
...
using namespace boost::units;
quantity<si::velocity, REAL> v;
然后有时我需要像
这样的东西quantity<si::velocity, REAL> v_halved;
v_halved = 0.5 * v;
这没关系,因为编译器将0.5
视为double
。但是,当REAL
有所不同时,我会收到编译错误,例如如果我将REAL
的定义更改为long double
,则编译抱怨:
error: no match for ‘operator*’ in ‘5.0e-1 * v’
/usr/include/boost/units/detail/one.hpp:58: note: candidates are: boost::units::one boost::units::operator*(const boost::units::one&, const boost::units::one&)
查看 Boost.Units documentation我发现operator*
已按以下方式重载:
// runtime scalar times quantity
template<typename Unit, typename X>
multiply_typeof_helper< X, quantity< Unit, X > >::type
operator*(const X & lhs, const quantity< Unit, X > & rhs);
虽然从定义中可以清楚地看出数量的标量和内部类型必须相同,但我希望编译器在隐式转换时自动转换类型(例如来自double
到long double
)。但是我认为我可能会遗漏一些东西,因为自动类型转换当然适用于其他简单的函数,如long double f(long double const & ld)
。
我的问题是我使用了v_halved = 0.5 * v
之类的表达式,而且我的项目已经变得相当大,而且现在只有在将REAL
定义为long double
之后我意识到这是一个问题。所以,我想知道一个解决方法/解决方案,我知道static_cast<REAL>(0.5)
将是一个解决方案,但我仍然觉得我遗漏了一些关于编译器无法自动将标量转换为正确的类型。
提前多多感谢!
答案 0 :(得分:3)
模板函数与非模板函数不同。编译器决定选择模板函数而不考虑隐式转换/促销。它只是寻找完全匹配。
这就是C ++在这方面的工作方式。
要获得完全匹配,您需要operator *
这样的定义(注意这个额外的模板参数Y):
template<typename Unit, typename X, typename Y>
typename multiply_typeof_helper< X, quantity< Unit, X > >::type
inline operator*(const Y & lhs, const quantity< Unit, X > & rhs)
{
return static_cast<X>(lhs) * rhs;
}
但我担心会干扰*
的提升定义。你可以玩这个 - 比如定义你自己的quantity
几乎完全来自boost - 但是我提出了以不同的方式定义乘法。
只需决定哪些内容更容易
L
- 0.5L
以使长双精度)