2017-07-30 89 views
2

試圖理解爲什麼類型推導在這裏與條件運算符一起失敗。
在這種情況下,標準中的某些東西試圖防止類型扣除?任何理解這一點的指針都會很棒。C++類型推斷遞歸函數

auto mfact(int i) 
{ 
    return (0==i) ? 1 : i * mfact(i-1); 
} 

auto mfact2(int i) 
{ 
    if (0 == i) 
     return 1; 

    else 
     return i * mfact2(i-1); 
} 
error: use of ‘auto mfact(int)’ before deduction of ‘auto’  
    return (0==i) ? 1 : i * mfact(i-1); 
+0

您應該*至少*發佈您的編譯器錯誤消息。在*最佳*後發佈[mcve]。 –

+0

一旦函數中的所有代碼都被檢查過,就會推導出返回類型。因此在函數的代碼中使用函數簽名是不成熟的。你必須在聲明中聲明返回類型。 –

+0

@RichardHodges如果您交換條件,將'return i * mfact2(i-1)'放在'return 1;'之上,'mfact2'無法編譯。這是否意味着該類型是由編譯器發現的第一個return語句推導出來的?使用GCC 7.1.1 – 2017-07-30 17:43:37

回答

4

mfact問題是三元運算符。該運算符的語義指定表達式的類型是兩個條件子表達式的常見類型(我正在解釋一下)。

什麼是常見類型?爲什麼它是int和...一個類型需要推導出來。
啊,沒問題!什麼類型可以被推斷?這是三元操作符的類型...

我們有雞和雞蛋的問題。整個函數定義不合格,因爲表達式的類型不能確定。

mfact2怎麼樣?它有兩個單獨的返回語句。第一個是純整數。由於一個函數只能有一個返回類型,所以返回類型推導要求兩個返回返回語句不會發生衝突。

引述C++ 14標準的修訂:

[dcl.spec.auto/2]

佔位符類型可以在 DECL說明符-SEQ,類型說明符-SEQ,變換的函數聲明出現功能id或 尾隨返回類型,在任何情況下,這樣的聲明是有效的。 如果函數聲明符包含尾隨返回類型 ([dcl.fct]),它指定函數的聲明返回類型。 如果函數的聲明返回類型包含佔位符 類型,則函數的返回類型從函數正文中的返回 語句推導出,如果有,則返回

所以一個return語句推斷類型是不夠的,:

[dcl.spec.auto/9]

如果與含有一個佔位符 類型聲明的返回類型的函數有多個return語句,返回類型推導爲 每個返回語句。如果推導的類型在每個 扣除中不相同,則該程序是不合格的。

在這個簡單的情況下,第一條語句要求它int,而第二個包含一個遞歸調用。由於相同的函數重載只能有一個返回類型,所以遞歸調用也必須是int。兩份退貨聲明同意。