模板操作符上的模糊过载 [英] Ambiguous overload on template operators

查看:197
本文介绍了模板操作符上的模糊过载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用两个包装类来定义真实和复杂的数据类型。每个类定义了重载的构造函数,以及四个算术运算符+, - ,*,/和五个赋值运算符=,+ =等。为了避免重复代码,我在考虑使用模板函数,当左和右 - 运算符的手边参数是不同的数据类型:

I am working on two wrapper classes that define real and complex data types. Each class defines overloaded constructors, as well as the four arithmetic operators +,-,*,/ and five assignment operators =,+= etc. In order to avoid repeating code, I was thinking of using template functions when the left- and right-hand-side arguments of an operator are of a different data type:

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

  ...
};

这里的问题是代码如下:

The problem here is that code like:

//main.cpp
void main() {
  Complex ac(2.0, 3.0);
  Real br(2.0);
  Complex cc = ac * br;
}

返回编译器( gcc )错误

returns the compiler (gcc) error ambiguous overload for 'operator*' in 'ac * br', as the compiler cannot tell the difference between:


  • template< class T> friend const复杂运算符*(const Complex& const T&) [with T = Real]

  • template< class T> friend const Real operator *(const T& cont Real&) [with T = Complex]

  • template <class T> friend const Complex operator*(const Complex&, const T&) [with T = Real]
  • template <class T> friend const Real operator*(const T&, cont Real&) [with T = Complex]

有没有一种方法来指定T不能是在类Real中的模板运算符*定义中的复杂?或者,我必须做没有模板和定义每个运算符的每个可能的参数数据类型的组合?或者有办法重新设计代码吗?

Is there a way to specify that T cannot be a Complex in the template operator* definition in the class Real? Or do I have to do without templates and define each operator for every possible combination of argument data types? Or is there a way to redesign the code?

推荐答案

啊,操作符的问题...

Ah, the problem of operators...

Boost创建了一个很好的库,所以通过提供最小的逻辑,所有其他变体都会为您自动添加。

Boost created a nice library so that by providing a minimum of logic all the other variations are automagically added for you!

Boost.Operators

现在为你的问题,实际上你注意到,你将必须定义操作符(int和double)的两种风格,而不是使用通用模板。如果这些操作符中有很多逻辑(我怀疑),你总是可以让他们调用一个通用的(模板)方法。

Now for your problem, actually as you noticed, you will have to define both flavors of the operators (int and double) rather than using a generic template. If there is a lot of logic in these operators (which I doubt), you can always have them call a common (templated) method.

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


$ b < (int)和Complex :: operator * =(double),并且将自动推导出独立版本:)

But if you use Boost.operators you only provide Complex::operator*=(int) and Complex::operator*=(double) and the stand-alone versions will be automatically deduced :)

这里,如果所有参数都是内置的。您也可以考虑 Boost.CallTraits ,它自动在by-value和by-ref之间选择,取决于参数是否是内置的。它是方便的模板。

(1) You might use pass by-value here, if all arguments are built-ins. You might also want to consider Boost.CallTraits, which automatically chooses between by-value and by-ref depending if the argument is built-in or not. It is handy for templates.

(2)当通过值返回参数时,将它们定义为 const const 关键字只意味着引用和指针,在这里没有什么阻止用户实例化一个'简单'复杂。 ..和你是幸运它不!

(2) When returning arguments by value, it is non-sensical to qualify them as const. The const keyword only means something for references and pointers, here nothing prevents the user to instantiate a 'simple' Complex... and you are fortunate it doesn't!

这篇关于模板操作符上的模糊过载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆