模板运算符上的模糊过载

时间:2009-10-27 10:15:25

标签: c++ templates operator-overloading

我正在研究两个定​​义真实和复杂数据类型的包装类。每个类定义重载的构造函数,以及四个算术运算符+, - ,*,/和五个赋值运算符=,+ =等。为了避免重复代码,我想在左右使用模板函数运算符的-hand-side参数具有不同的数据类型:

// 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;
}

为'ac * br'中的'operator *'返回编译器( gcc )错误模糊重载,因为编译器无法区分:

  • 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 =复杂]

有没有办法在Real类中的模板运算符*定义中指定T不能是Complex?或者我是否必须没有模板并为每种可能的参数数据类型组合定义每个运算符?或者有没有办法重新设计代码?

3 个答案:

答案 0 :(得分:2)

啊,运营商的问题......

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)如果所有参数都是内置的,你可以在这里使用pass by-value。您可能还需要考虑Boost.CallTraits,它会根据参数是否内置自动选择by-value和by-ref。它对模板很方便。

(2)当按值返回参数时,将它们限定为const是不合理的。 const关键字仅表示引用和指针的内容,此处没有任何内容阻止用户实例化“简单”Complex ...而且您很幸运它没有!

答案 1 :(得分:1)

您可以使Real或Complex类具有非全局乘法运算符。

class Real 
{
  ........

  template <class T> const Real operator*(const T&);
  const Real operator*(const Real&);

};

答案 2 :(得分:0)

您可以使复杂构造函数显式化吗? 这意味着不允许从Real到Complex的隐式转换,并且应该消除运算符*

的歧义