一、問題
在新的C++標准中,auto的應用范圍越來越廣,但是比較常用的典型場景在於使用一個auto接收一個函數的返回值。問題是對於一個函數的auto返回值,這個返回值是如何確定的?特別是一個函數有多個返回值的時候。
直觀上的理解是當一個函數體(function body)解析(parse)完成之后,遍歷它的所有語句(statement),並找到其中的return語句,逐個推導它們的返回值。
二、gcc的做法
從代碼上看,gcc的這個解析是在函數體解析的時候同步進行,而不是在整個函數體解析完成之后再事后遍歷。好在從這個代碼看其實也比較直觀,就是在遇到return語句的時候進行特殊處理,將這個return之后表達式的類型和當前解析函數。在假設return必定出現在函數體內的前提下,必定可以將這個表達式的類型賦值給當前函數(current_function_decl全局變量)的返回值中。
gcc-10.1.0\gcc\cp\typeck.c
cp_parser_jump_statement==>>finish_return_stmt==>>check_return_expr
tree
check_return_expr (tree retval, bool *no_warning)
{
……
functype = TREE_TYPE (TREE_TYPE (current_function_decl));
/* Deduce auto return type from a return statement. */
if (FNDECL_USED_AUTO (current_function_decl))
{
tree pattern = DECL_SAVED_AUTO_RETURN_TYPE (current_function_decl);
……
if (type == error_mark_node)
/* Leave it. */;
else if (functype == pattern)
apply_deduced_return_type (current_function_decl, type);
else if (!same_type_p (type, functype))
{
if (LAMBDA_FUNCTION_P (current_function_decl))
error_at (loc, "inconsistent types %qT and %qT deduced for "
"lambda return type", functype, type);
else
error_at (loc, "inconsistent deduction for auto return type: "
"%qT and then %qT", functype, type);
}
functype = type;
}
……
}
三、C++標准的說明
這個標准比較冗長一些,當然也比較詳細和精確
四、測試代碼
tsecer@harry: cat c++.lambda.return.type.deduce.cpp
auto foo()
{
return 1;
}
int main(int argc, const char * argv[])
{
auto xxx = [](int x)
{
if (x > 10)
{
return x - 10;
}
return x;
};
return xxx(argc) + foo();
}
tsecer@harry: gcc -std=c++14 c++.lambda.return.type.deduce.cpp
tsecer@harry:
五、變量auto的推導
我記得之前看過是通過類似於模板的推導規則實現的。