2009-10-27 58 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