簡體   English   中英

轉換運算符重載歧義,編譯器不同

[英]conversion operator overloading ambiguity, compilers differ

我已經看到了關於此的其他問題,但沒有一個完全解釋它。 編譯器處理以下兩種情況的正確方法是什么? 我用gcc 4.7.1(使用-std = c ++ 0x),VS2010和VS2012嘗試了一下,得到了不同的結果:

例1:

struct BB
{
 // generic cast
 template<typename T>
 operator T() const
 {   
   return 0;
 }

 // string cast
 operator std::string() const
 { 
   return string("hello");
 }
};

int main()
{
  BB b;
  string s = b;
}

輸出:

  • gcc 4.7.1:好的
  • VS2010:好的
  • VS2012:失敗:“無法從BB轉換為字符串”

例2:

struct BB
{
 // generic cast
 template<typename T>
 operator T() const
 {   
   return 0;
 }

 // string cast
 operator std::string() const
 { 
   return string("hello");
 }
};

int main()
{
  BB b;
  string s = (string)b;

輸出:

  • gcc 4.7.1:失敗:調用重載字符串(BB&)是不明智的
  • VS2010:好的
  • VS2012:失敗:“無法從BB轉換為字符串”

你的第二個版本與C風格的演員是不明確的。 問題是static_cast<std::string>有兩種方法可以將BB類的實例轉換為字符串。 顯而易見的路徑是使用非模板std :: string強制轉換運算符直接轉換為字符串。 有一條更加狡猾的道路,除了VS2010以外都發現了它。 另一個路徑是使用模板轉換運算符將BB轉換為字符串的分配器,然后使用此分配器構造空字符串。

模板轉換操作符是潛在危險的野獸。 您剛剛為編譯器提供了將BB轉換為任何內容的工具。

你的第一個版本逃避了這個問題,因為std::basic_string(const _Alloc& __a)是一個顯式的構造函數。 顯式構造函數可以由顯式轉換使用,但不能由隱式轉換使用。 正是這個構造函數加上轉換為創建歧義的分配器,並且此路徑不能與隱式轉換一起使用。

至於為什么VS1012在隱含轉換上失敗,它可能是VS2012中的一個錯誤,或者可能是C ++ 11創建了從BBstd::string更多途徑。 我不是C ++ 11專家。 我甚至不是新手。

還有一件事:如果你使用過,你的代碼會失敗得更厲害

 std::string s;
 s = b;

賦值運算符與模板轉換運算符一起創建了更多從bs 系統應該將b轉換為std::stringchar還是char*

結論:您真的應該重新考慮使用模板轉換運算符。

在一些編譯器下失敗的原因是因為他們試圖找出你在做什么的不同長度。 罪魁禍首是模板化的操作員調用。

正如這個SO問題所解釋的那樣,必須顯式調用模板化運算符( b.operator()<std::string>如果你想調用template<typename T> operator(); ),但是,沒有辦法調用你的模板化運算符:

b.operator std::string()<std::string>; //invalid
b.operator std::string <std::string>(); //also invalid, string takes no template arguments
// a bunch more weird syntax constructions...

問題來自於operator后面的名稱取決於模板參數,因此無法指定它。 gcc和VS2012弄清楚你在做什么,並注意到它們可以適應轉換到模板或明確定義的一個=>模糊的調用。 VS2010沒有這樣做並正在調用其中一個,你可以通過調試找到哪一個。

模板專業化可能在這樣的情況下有所幫助,但是,試圖定義

// string cast
template<>
operator std::string() const
{ 
    return string("hello");
}

將失敗,因為編譯器無法區分該函數與沒有template<>的常規函數​​之間的區別。 如果原型中有一些參數它會工作,但operator typename確實有...

長話短說 - 避免模板轉換運算符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM