2011-08-24 50 views
1

假設我們有下面的代碼:不止一個運營商,這些操作數相匹配

struct int64 
{ 
    long long value; 

    int64() : value(0) {} 
    int64(signed char i8) : value(i8) {} 
    int64(unsigned char u8) : value(u8) {} 
    int64(short i16) : value(i16) {} 
    int64(unsigned short u16) : value(u16) {} 
    int64(int i32) : value(i32) {} 
    int64(unsigned u32) : value(u32) {} 
    int64(long long i64) : value(i64) {} 
    int64(unsigned long long u64) : value(u64) {} 
    int64(const int64& i64) : value(i64.value) {} 

    int64& operator+=(const int64& rhs) { return value += rhs.value, *this; } 
    int64& operator-=(const int64& rhs) { return value -= rhs.value, *this; } 

    friend int64 operator+(const int64& lhs, const int64& rhs) { return int64(lhs) += rhs; } 
    friend int64 operator-(const int64& lhs, const int64& rhs) { return int64(lhs) -= rhs; } 

    operator char() const { return (char)value; } 
    operator short() const { return (short)value; } 
    operator int() const { return (int)value; } 
    operator long long() const { return value; } 
}; 

編譯時的這段代碼:發生

int64 q = 500; 
int64 m = q + 1024; 

錯誤有4類似的轉換提供給1024和一個因對於q爲整型,爲了解決這個問題,我從int64中刪除了operator XX,並添加了以下代碼:

template <typename n> 
operator n() const { return (n)value; } 

現在我可以執行以下代碼:

int64 q = 500; 
int64 m = q + 1024; 
short r = q; 

模板定義可與Visual C++GCC編譯器,但Intel C++編譯器。

我該如何編寫適用於這些編譯器的轉換運算符?

回答

1

你應該寫operator+定義爲所有您支持的類型:

int64 operator+(int num) { 
    return int64(value + num); 
} 

int64 operator+(short num) { 
    ... 
} 

... 

你添加intint64和結果分配到int64,但它沒有一個拷貝構造函數等等它將它轉換爲一些整型,並試圖對所有這些轉換運算符和構造函數做一些奇怪的事情。

+0

編譯器生成的問題出了什麼問題? –

+0

@你不會放棄生成的編譯器(至少是copy ctor)嗎? –

+0

如果您定義了任何其他構造函數,而不是複製函數或賦值運算符,則會放棄編譯器生成的默認構造函數。 –

0

這裏的問題在於,如果您既提供了內置類型的構造函數,又提供了同一類型的轉換運算符,然後使用這兩種類型的表達式,C++就無法真正地確定它應該採用哪種方式去。因此,「myInt64Variable + 1024」可能意味着「(int)myInt64Variable + 1024)」通過轉換爲int運算符或「myInt64Variable +(int64)1024」通過構造函數。

根據我的經驗,處理此問題的最佳方法是不提供轉換運算符,或者如果您必須擁有它們,則可以創建toInt()函數或類似函數。從自定義類型到內置類型的任何轉換都將是有損的轉換,否則爲什麼要使用自定義類型?並且在執行有損轉換時讓人們注意是一件好事。

0

與C++ 11(其中,當這個問題被問剛剛被批准)開始,你可以標記轉換explicit

struct int64 
{ 
    // ... 

    explicit operator char() const { return (char)value; } 
    explicit operator short() const { return (short)value; } 
    explicit operator int() const { return (int)value; } 
    explicit operator long long() const { return value; } 
}; 

這應該在所有主要的編譯器的最新版本的工作(我測試過的所有人都有足夠的C++ 11支持)。然而

struct int64 
{ 
    // ... 

    template <typename n> 
    explicit operator n() const { return static_cast<n>(value); } 
}; 

,這意味着:您還可以,如果你想申請給你的模板轉換操作符,雖然我更喜歡的四個非模板轉換(加,這墜毀ICC的版本,我試了一下!)你不能做short r = q;。對我來說,這是一件好事,因爲縮小轉換真的應該是

short r = static_cast<short>(q); 
相關問題