尾置返回類型
尾置返回類型(trailing return type)是C++11中新增的特性副编,任何函數(shù)的定義都可以使用尾置返回類型录煤,但是尾置返回類型更適合用于返回類型比較復雜的場景,如返回一個數(shù)組指針橘荠。下面的例子是返回一個指向維度為10的數(shù)組指針的函數(shù)定義方法:
int (*func(int i))[10]
下面逐層理解上述例子的含義:
- func(int i)表示調(diào)用函數(shù)時幌衣,需要一個int類型的參數(shù)矾削;
- (*func(int i))表示對調(diào)用func的結(jié)果執(zhí)行解引用的操作;
- (*func(int i))[10]表示解引用之后得到一個維度為10的數(shù)組豁护;
- int (*func(int i))[10]表示數(shù)組的數(shù)據(jù)類型為int哼凯;
若使用尾置返回類型,上述函數(shù)的定義可以寫成:
auto func(int i)->int (*)[10]
使用尾置返回類型之后楚里,函數(shù)的定義更加清晰易懂断部;同時注意到,尾置類型通常要和auto結(jié)合使用班缎。
尾置lambda的返回類型
默認情況下蝴光,如果一個lambda中包含一個return之外的任何語句,編譯器將假定此lambda的返回void吝梅。如下面的例子將vector中的負數(shù)轉(zhuǎn)成正數(shù):
std::vector<int> v {1, -9, 8, -3, 5};
transform(v.begin(), v.end(), v.begin(), [](int i){return i<0 : -i : i;});
上面的例子可以正常編譯通過虱疏,若修改成if/else的形式這編譯無法通過:
std::vector<int> v {1, -9, 8, -3, 5};
transform(v.begin(), v.end(), v.begin(), [](int i){
if (i<0) return -i; else return i;
});
下面的這段描述來自 《C++ Primer》(第5版)惹骂,我分別在gcc4.8.5和gcc5.4.0的環(huán)境上測試了苏携,都無編譯錯誤,也許高版本的編譯器對此有優(yōu)化对粪。感謝boringcat的指正右冻。
此時lambda表達式默認返回類型為void装蓬,而return了一個int,因此無法編譯通過纱扭。上述的例子可以通過尾置返回類型來指定具體的返回類型牍帚,如:
std::vector<int> v {1, -9, 8, -3, 5};
transform(v.begin(), v.end(), v.begin(), [](int i) -> int {
if (i<0) return -i; else return i;
});
尾置模板的返回類型
模板函數(shù)定義和調(diào)用如下:
template<typename R, typename T, typename U>
R add(T t, U u)
{
return t+u;
}
int a =1;
float b = 2.0;
auto c = add<decltype(a+b)>(a, b);
問題:add函數(shù)的返回類型能否通過decltype獲取呢?
template<typename R, typename T, typename U>
decltype(t+u) add(T t, U u) // error: t乳蛾、u尚未定義
{
return t+u;
}
上述在使用decltype(t+u)時暗赶,t、u尚未定義肃叶,編譯失旛逅妗;
問題:能否通過decltype(T()+U())推導呢因惭?不一定可以岳锁,因為T、U可能不包含無參數(shù)的構(gòu)造函數(shù)蹦魔。但可以按照下面方式修改:
decltype( (*(T*)0) + (*(U*)0) )
雖然上述方式可以解決問題激率,但是寫法很晦澀,通過auto勿决、decltype和尾置返回類型乒躺,可以清晰的寫出上述的邏輯。
template<typename R, typename T, typename U>
auto add(T t, U u) ->decltype(u+t)
{
return t+u;
}
一個函數(shù)wrapper
int& func(int& i );
float func(int& f);
template<typename T>
auto func(T& val) -> decltype(func(val))
{
return func(val);
}
尾置返回類型和auto剥险、decltype的結(jié)合聪蘸,可以有效的解決函數(shù)返回類型依賴于參數(shù)推導來確定的問題。