2009-10-27 59 views
2

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

// 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)错误暧昧过载'operator *'in'ac * BR”,因为编译器不能告诉之间的区别:

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

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

回答

2

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

加速创造了一个很好的库,以便通过提供最低的逻辑所有其他变化都会自动添加给你!

看看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你只提供复杂::运算符* =(int)和复杂::运算符* =(双)和单机版本将自动推断:)

(1)如果所有参数都是内置的,则可以在这里使用传值。您可能还需要考虑Boost.CallTraits,该参数根据参数是否内置而自动在by-value和by-ref之间进行选择。它对模板很方便。

(2)按值返回参数时,将它们限定为const是不合理的。 const关键字仅意味着引用和指针,这里没有任何东西阻止用户实例化'简单'Complex ...你很幸运,它不会!

1

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

class Real 
{ 
    ........ 

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

}; 
0

你可以使复杂构造函数显式吗? 这将意味着从皇家到复杂的隐式转换是不允许的,应该消除歧义操作*

+0

确实应该使构造函数明确(编辑问题)。但是,在这种情况下,使它们显式不会消除编译错误。 – ASV 2009-10-27 13:54:39