1. 程式人生 > >重新認識三目運算子:? :

重新認識三目運算子:? :

三目運算子即條件表示式運算子:? :,其基本形式如下:

logical-OR expression ? expression : conditional-expression

大家都知道該運算子的作用,當?前面的條件為真時,就執行:前面的表示式,如果條件為假時,則執行:後面的表示式,並返回相應的計算結果。

但是在使用過程中,一直忽略了一個東西,那就是條件表示式運算子的返回結果的型別是什麼?

可能一開始我們會想當然的認為:如果返回值為expression計算的結果,則其結果型別就為expression表示式的型別;反之,如果返回值為conditional-expression計算的結果,則其結果型別就為conditional-expression

表示式的型別。結果很遺憾,那樣的想法是錯誤的。

事實上,?:運算子所計算的結果的型別會同時根據expressionconditional-expression的型別來產出一個共通型別(common type),所謂共通型別就是它們倆都可以正確或安全的轉換為那個型別(本人自己的理解)。具體的轉換規則可以參考 Conditional Operator: ? :條件表示式運算子

可以通過以下程式碼進行驗證上面的事實:

int size1 = sizeof(true ? 2 : 2.4);
int size2 = sizeof(true ? 'A' : 2);
std::cout <<
size1 << std::endl; // 在 gcc 7.3.0 上執行的結果為 8 std::cout << size1 << std::endl; // 在 gcc 7.3.0 上執行的結果為 4

有些人會說,搞了半天,貌似和我們沒啥關係,我們平常用的只是一個結果值,而並不去關心它的型別。的確,可能我們很少會關注到這個性質,但是相信好多人應該都遇見過 std::common_type 這個東東,而它裡面的實現就使用了 ?: 運算子的這一特性。

我也是在學習C++11過程中看到 std::common_type (用來處理共通型別 )這個東西,對其實現裡的那個三目運算子表示式不是很理解,於是網上查詢相關資料,在此做一個記錄。

// c++11
template <class... Types> struct common_type;

template <class T> struct common_type<T> {
  typedef T type;
};

template <class T, class U> struct common_type<T,U> {
  typedef decltype(true?declval<T>():declval<U>()) type; // 之前一直不理解
};

template <class T, class U, class... V> struct common_type<T,U,V...> {
  typedef typename common_type<typename common_type<T,U>::type,V...>::type type;
};