2012-09-05 44 views
7

只是爲了看看它是如何工作的,我看着在頭type_traits中的libstdC++實現的std::common_type。我不得不承認我不太瞭解它是如何工作的。這裏是:的std :: common_type實施

/// common_type 
template<typename... _Tp> 
    struct common_type; 

template<typename _Tp> 
    struct common_type<_Tp> 
    { typedef _Tp type; }; 

template<typename _Tp, typename _Up> 
    struct common_type<_Tp, _Up> 
    { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; }; 

template<typename _Tp, typename _Up, typename... _Vp> 
    struct common_type<_Tp, _Up, _Vp...> 
    { 
     typedef typename 
     common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; 
    }; 

我很好理解第一,第二和第四聲明是如何工作的。但是,我無法理解第三個聲明是如何工作的。有人可以試着解釋這裏使用的機制嗎?

回答

8

首先,std::declval<T>()產生一個類型爲T的r值。試圖對值做任何事情都會失敗,因此它只能用於未經評估的上下文中。接下來,三元運算符將它的類型推斷爲兩個參數通用的最專用類型(如果沒有這種類型,則失敗)。因此,表達式

true? declval<T0>(): declval<T1>() 

的類型是T0T1最專業的常見類型。所有剩下的就是將這個表達式轉換爲一個類型並確保它不被評估。 decltype(expr)就是這樣做的。顯然,邏輯的兩個參數版本:其他人在那裏處理角落案例(一個參數)並利用兩個參數版本來產生常見類型的任意類型。

3

第三版本使用條件運算以確定常見的類型。它的規則在標準的第5.16節中有相當長的描述,所以我不確定我應該在這裏複製它們。

簡單地說,表達:

boolean-expression ? second-operand : third-operand 

具有第二和第三運算數的一個「普通型」,如果這樣的存在。然後使用decltype說明符將表達式「轉換」爲類型說明符。

+3

+1,一個不錯的閱讀* magic *,包括三元運算符:[Conditional Love:FOREACH redux](http://www.artima.com/cppsource/foreach.html) –

+0

好的,我想我終於得到了訣竅。所以它依賴於三元運算符根據它的操作數推斷它的返回類型的事實。它沒有想到這一點。謝謝! – Morwenn

1

長話短說:該decltype正在使C++編譯器確定最近的祖先類型吧。

第三操作有導致靜態類型的兩種可能的表達式的最接近的祖先。

E.g:

甲從乙繼承

X繼承選自Y選自B

<expression> ? <expression with static type A> : <expression with static type X> 
    = <expression with static type B> // this is how the C++ parser sees it 

繼承這是怎樣的C++語言的作品。 decltype只是使typedef成爲該表達式結果的靜態類型(無論C++編譯器確定它是哪種類型)

+0

這在使用術語* ancestor *和使用繼承的例子中有些誤導。確實如此,但它的功能更多,如果其中一種類型是*可轉換*到另一種類型,它將選擇第二種類型,例如'(true?1,1)'具有'double'類型作爲' int'可以轉換爲double,儘管沒有*祖先*或*繼承*。 –