3

这是一个非常简约的例子。我以下列方式使用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 文档,我发现它的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);

尽管从定义中可以清楚地看出数量的标量和内部类型必须相同,但我希望编译器在可以隐式进行转换时自动转换类型(例如 from doubleto long double)。但是我认为我可能会遗漏一些东西,因为自动类型转换当然适用于其他简单的函数,比如long double f(long double const & ld).

我的问题是我已经使用v_halved = 0.5 * v了很多类似的表达式,我的项目已经变得相当大,而且直到现在,在必须定义之后REALlong double才意识到这是一个问题。所以,我想知道一个解决方法/解决方案,我知道这static_cast<REAL>(0.5)将是一个解决方案,但我仍然觉得我错过了一些关于编译器无法自动将标量转换为正确类型的东西。

提前非常感谢!

4

1 回答 1

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使 long double 常量)
  • 或与模板进行一些组合。
于 2012-10-15T20:25:48.953 回答