• 文章
  • C++0x 字尾返回型別
2011年6月15日 (最後更新: 2011年6月23日)

C++0x 字尾返回型別

評分: 3.8/5 (95 票)
*****
這是我寫的關於 C++0x 字尾返回型別的文章。它也釋出在我的部落格 (SFML Coder) 上。 如果您有任何更正或改進的建議,請私信我或 給我發郵件! 感謝 jsmith 提供了比我原來的例子更合適的例子。



現在開始介紹另一個小的 C++0x 特性。 像 auto 一樣,它受 Microsoft Visual C++ 2010 和 MinGW 支援。 如果您有不同的編譯器,那麼嘗試一下也沒什麼壞處。 請記住,如果您遇到編譯器錯誤,則可能意味著您的編譯器不支援該功能。

讓我們用一個例子直奔主題。 考慮以下我們通常如何編寫函式的示例

1
2
3
4
5
bool Init()
{
	// etc
	return true;
}

這是使用尾隨返回型別的方式

1
2
3
4
5
auto Init() -> bool
{
	// etc
	return true;
}


我們為什麼要這樣做? 畢竟,這需要做更多的工作。 好了,是的,在這種情況下需要做更多的工作,但是現在考慮一個真實的例子。 在我的遊戲引擎日誌中,我有一個函式,它接受一個字串,對其應用一些格式並返回它。 字串型別是 typedef'd std::string 稱為 StringIcanos::System 名稱空間中。

這就是我利用此 C++0x 特性之前編寫函式的方式。

1
2
3
4
Icanos::System::String Icanos::System::FormattedLog::ApplyIndent(const String& message, const String& source)
{
  // etc
}


我必須完全限定 String 返回型別。 但是,如果我可以將返回型別放在後面,那麼 String 型別將已經在作用域內,因為我們已經限定了函式的作用域,從而簡化了表示法。

1
2
3
4
auto Icanos::System::FormattedLog::ApplyIndent(const String& message, const String& source) -> String
{
  // etc
}


在函式名稱之後,Icanos::System 中的所有內容已經在作用域中,因此我們無需再次限定 String 上的名稱空間。

現在,如果我們的返回型別依賴於引數型別(在模板函式中),我們可能還需要使用字尾返回型別。感謝 jsmith 的補充。
天真地,我們應該喜歡這樣做
1
2
template <class S, class T>
decltype(s + t) Add(const S& s, const T& t) 

當然,它不會編譯,因為 st 不在作用域內。 但是它們在引數列表之後才在作用域內
1
2
template <class S, class T>
auto Add(const S& s, const T& t) -> decltype(s + t)


這是解決此問題的一種好方法,僅供您參考,這是 Stroustrup 在沒有後綴返回型別的情況下提出的較小惡魔的版本。 它顯然是劣等的。
1
2
template <class S, class T>
decltype(*(S*)(0) + *(T*)(0)) Add(const S& s, const T& t)


好了,希望您喜歡我對字尾返回型別的介紹 - 您也可能看到它被稱為尾隨返回型別。 如果您想了解更多資訊,請檢視 Dr. Stroustrup 的 FAQ
http://www2.research.att.com/~bs/C++0xFAQ.html#suffix-return
(巧合的是,最初建議(如 Stroustrup 的 FAQ 中所述)字尾返回型別使用 [] 而不是 auto 來表示。 但是,由於爭議,建議使用 auto 作為替代方法。 如果使用 [],則 MinGW 和 Microsoft Visual C++ 都會生成編譯器錯誤。)