我正在研究两个定义真实数据类型和复杂数据类型的包装类。每个类都定义了重载的构造函数,以及四个算术运算符+、-、*、/和五个赋值运算符=、+=等。为了避免重复代码,我想到了在左右移动时使用模板函数- 运算符的手侧参数具有不同的数据类型:
// real.h
class Real {
public:
explicit Real(const double& argument) {...}
explicit Real(int argument) {...}
...
friend const operator*(const Real&; const Real&);
template <class T> friend const Real operator*(const Real&, const T&);
template <class T> friend const Real operator*(const T&, cont Real&);
// Here, T is meant to be a template parameter for double and int
// Repeat for all other arithmetic and assignment operators
};
// complex.h
class Complex {
public:
explicit Complex(const Real& realPart) {...}
explicit Complex(const Real& realPart, const Real& imaginaryPart) {...}
// Overload for double and int data types
...
friend const operator*(const Complex&, const Complex&);
template <class T> friend const Complex operator*(const Complex&, const T&);
template <class T> friend const Complex operator*(const T&, cont Complex&);
// Here, T is is a template parameter for Real, double and int
...
};
这里的问题是代码如下:
//main.cpp
void main() {
Complex ac(2.0, 3.0);
Real br(2.0);
Complex cc = ac * br;
}
返回编译器 (gcc) 错误“ac * br”中“operator*”的不明确重载,因为编译器无法区分以下内容:
-
template <class T> friend const Complex operator*(const Complex&, const T&)
[T = Real] -
template <class T> friend const Real operator*(const T&, cont Real&)
[其中 T = 复数]
有没有办法指定 T 不能是 Real 类模板运算符*定义中的复数?或者我是否必须不用模板并为参数数据类型的每种可能的组合定义每个运算符?或者有没有办法重新设计代码?
最佳答案
啊,运营商的问题……
Boost 创建了一个很好的库,通过提供最少的逻辑,所有其他变体都会自动为您添加!
看看Boost.Operators !
现在,对于您的问题,实际上正如您所注意到的,您必须定义两种类型的运算符(int 和 double),而不是使用通用模板。如果这些运算符中有很多逻辑(我对此表示怀疑),您始终可以让它们调用通用(模板化)方法。
template <typename T>
Complex complex_mult_impl(T const& lhs, Complex const& rhs) { ... } // Note (1)
// return type is not 'Complex const', see (2)
Complex operator*(int lhs, Complex const& rhs)
{
return complex_mult_impl(lhs,rhs);
}
但是,如果您使用 Boost.operators,则只需提供 Complex::operator*=(int) 和 Complex::operator*=(double) ,独立版本将自动推导:)
(1) 如果所有参数都是内置参数,您可以在此处使用按值传递。您可能还想考虑Boost.CallTraits ,它会自动在按值和按引用之间进行选择,具体取决于参数是否内置。对于模板来说很方便。
(2) 当按值返回参数时,将它们限定为 const 是没有意义的。 const
关键字仅意味着引用和指针,这里没有什么可以阻止用户实例化“简单”复杂
...幸运的是它没有!
关于c++ - 模板运算符的不明确重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1629829/