1. 程式人生 > >【C++11學習筆記】返回型別後置語法

【C++11學習筆記】返回型別後置語法

本次學習3個知識點:
(1)auto推導型別
(2)decltype推導表示式的型別
(3)返回型別後置語法

泛型程式設計中經常遇到的寫一個加法函式:

template <typename R, typename T, typename U>
R add(T t, U u) {
    return (t + u);
}

int a = 10;
float b = 20.0;
auto c = add<decltype(a + b)>(a, b);

這裡我們並不關心a+b結果的型別,故使用decltype推導返回值型別。這個add函式有沒有改進方法,畢竟既然外部不知道add內部是怎麼操作的、返回的結果應該是什麼型別。

根據這個想法,我們把上述例子改進為:

template <typename T, typename U>
decltype(t + u) add(T t, U u) {
    return (t + u);
}

邏輯上沒有問題,返回型別由decltype推導,但是無法編譯通過,原因是C++的返回值是前置語法,在返回值定義的時候引數變數還不存在,這裡會提示t、u尚未定義。

既然如此,那我們把decltype中的表示式稍微改進一下,以便編譯通過

template <typename T, typename U>
decltype(T() + U()) add(T t, U u) {
    return
(t + u); }

但T、U可能是沒有無引數的建構函式的類,利用一個小技巧:0(或NULL)可以轉換成任意型別指標,改進為正確版本:

template <typename T, typename U>
decltype((*(T*)0) + (*(U*)0)) add(T t, U u) {
    return (t + u);
}

功能無誤、編譯正確,但有點複雜,一點都不“C++11”。這裡要用到上面講的第3個知識點:返回型別後置語法,將decltype和auto結果起來完成返回值型別的推導,

template <typename T, typename U>
auto
add(T t, U u) -> decltype(t + u) { return t + u; }

是不是特別簡潔~

初次看上述程式碼,可能有一個疑問就是會不會(t + u)會運算兩次,影響“效能”。絲毫不會,原因是decltype推到表示式型別是在編譯期完成的,並且不會真正計算表示式的值,型別sizeof推導表示式型別大小一樣。

【參考:祁宇《深入應用C++11程式碼優化與工程級應用》】