2016-10-02 102 views
5

我在讀一本書,它解釋了C++特徵,並且有一個例子來自C++ type_traits頭文件,其中有一個奇怪的?:用法,下面是來自相應/ usr/include/C++ /的引用。 ..文件:奇怪的運算符?:decltype的用法

template<typename _Tp, typename _Up> 
    static __success_type<typename decay<decltype 
         (true ? std::declval<_Tp>() 
         : std::declval<_Up>())>::type> _S_test(int); 

撇開給出聲明的目的,?:操作者的使用讓我爲難,在這個代碼。如果第一個操作數是true,那麼將始終選擇std::declval<_Tp>()作爲評估的結果。 該declval操作數選擇如何實際工作?

編輯:最初閱讀Nicolai M. Josuttis的「The C++ Standard Library:A Tutorial and Reference,2nd ed。」,第125頁。但是與我的GCC頭文件相比,它的格式稍微簡單一些。

+1

什麼是書btw? – manatttta

+0

這裏重要的是表達式的類型,而不是評估哪個部分。 – Mat

+0

馬特說什麼。該表達式用於使用三元條件運算符類型演繹機制(您可以在這裏閱讀它(http://en.cppreference.com/w/cpp/language/operator_other))。 – StoryTeller

回答

9

在表達式true ? std::declval<_Tp>() : std::declval<_Up>()中總是選擇第一個選項,但整個表達式必須是有效的表達式。所以std::declval<_Up>()必須是有效的,這意味着_Up必須是一個可接受零參數的可調用對象。除此之外,_Tp()_Up()必須返回相同類型(或其中一個類型必須隱式轉換爲另一個類型),否則三元迭代器將無法選擇返回值。

這種技術被稱爲SFINAE(替代失敗不是錯誤)。這個想法是,如果模板實例化失敗,那麼它不是一個錯誤,這個模板只是被忽略,編譯器搜索另一個模板。

+1

只要隱式轉換序列可用,它們不必返回完全相同的類型。 – StoryTeller

+0

@StoryTeller,謝謝你,我已經糾正了答案。 –

3

這裏的想法是,?:要求第二個和第三個操作數具有相同的類型,或者一個類型可以轉換爲另一個類型。

否則,函數的實例化將失敗,並選擇其他一些超載。