C++运算符重载和隐式转换

Sad*_*ido 7 c++ operator-overloading implicit-conversion

我有一个类封装了一些算术,比方说定点计算.我喜欢重载算术运算符的想法,所以我写了以下内容:

class CFixed
{
   CFixed( int   );
   CFixed( float );
};

CFixed operator* ( const CFixed& a, const CFixed& b )
{ ... }
Run Code Online (Sandbox Code Playgroud)

一切正常.我可以写3*CFixed(0)和CFixed(3)*10.0f.但是现在我意识到,我可以用整数操作数实现operator*更加有效.所以我重载它:

CFixed operator* ( const CFixed& a, int b )
{ ... }
CFixed operator* ( int a, const CFixed& b )
{ ... }
Run Code Online (Sandbox Code Playgroud)

它仍然有效,但现在CFixed(0)*10.0f调用重载版本,将float转换为int(我希望它将float转换为CFixed).当然,我也可以重载浮点版本,但它似乎是我的代码组合爆炸.有没有解决方法(或者我设计我的课程错了)?如何告诉编译器只使用int调用operator*的重载版本?

P S*_*ved 5

float你也应该重载类型。int从到用户指定类型 ( ) 的转换CFixed的优先级低于到 的内置浮点积分转换float。因此编译器将始终选择 function with ,除非您也int添加 function with 。float

有关更多详细信息,请阅读 C++03 标准的 13.3 部分。感受到痛苦。

看来我也已经失去了踪迹。:-( UncleBens报告说仅添加 float 并不能解决问题,因为double还应该添加 with 版本。但无论如何,添加与内置类型相关的多个运算符都是乏味的,但不会导致组合提升。


Unc*_*ens 2

假设您希望为任何整数类型(而不仅仅是int)选择专用版本,您可以做的一件事是将其作为模板函数提供,并使用 Boost.EnableIf 从可用重载集中删除这些重载,如果操作数不是整型。

#include <cstdio>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>

class CFixed
{
public:
   CFixed( int   ) {}
   CFixed( float ) {}
};

CFixed operator* ( const CFixed& a, const CFixed&  )
{ puts("General CFixed * CFixed"); return a; }

template <class T>
typename boost::enable_if<boost::is_integral<T>, CFixed>::type operator* ( const CFixed& a, T  )
{ puts("CFixed * [integer type]"); return a; }

template <class T>
typename boost::enable_if<boost::is_integral<T>, CFixed>::type operator* ( T , const CFixed& b )
{ puts("[integer type] * CFixed"); return b; }


int main()
{
    CFixed(0) * 10.0f;
    5 * CFixed(20.4f);
    3.2f * CFixed(10);
    CFixed(1) * 100u;
}
Run Code Online (Sandbox Code Playgroud)

当然,您也可以使用不同的条件来使这些重载仅在 T=int 时可用:typename boost::enable_if<boost::is_same<T, int>, CFixed>::type ...

至于类的设计,也许你可以更多地依赖模板。例如,构造函数可以是一个模板,并且如果您需要区分整型和实数类型,则应该可以使用此技术。