2014-03-06 44 views
8

我玩弄多態性可變參數lambda表達式上鏘,發現鏘並不喜歡這個這個遞歸多態C++ 1y lambda調用有什麼問題?

#include <iostream> 

int main() { 
    auto append = [](auto &&cnt, auto &&me, 
        auto &&a, auto &&p1, auto &&...p) -> decltype(auto) 
    { 
     if(sizeof...(p) > cnt) 
      return me(++cnt, me, a << p1, p..., 0); 
     return a; 
    }; 
    append(0, append, std::cout, 1, 2, 3, 4); 
} 

它旨在putput「1234」。一個0被添加到參數列表中(並且每次都會帶走前面的參數中的一個),並且計數器監視什麼時候我們需要停止,因爲我們會碰到一個虛擬的0

但鏘抱怨

fatal error: recursive template instantiation exceeded maximum depth of 256 

在其backtract,大部分的功能框架是

main.cpp:6:20: note: in instantiation of function template specialization 'main()::<anonymous class>::operator()<int &, <lambda at main.cpp:4:19> &, std::basic_ostream<char> &, int &, int &, int &, int>' requested here 
      return me(++cnt, me, a << p1, p..., 0); 
       ^

這似乎是一個自稱遞歸函數模板,我看不到無限模板實例化瘋狂。有人可以擺脫一些光?標準perpahs是否禁止像lambda一樣遞歸?

+0

@dyp謝謝啊!請讓它成爲答案,我會接受 –

回答

10

這應該是[dcl.spec.auto]/11(引用n3797)

如果需要的實體與undeduced佔位符類型的類型來確定的表達式的類型, 程序是不合格的。但是,如果在函數中看到return語句,則從該語句推導出的返回類型 可用於該函數的其餘部分,包括其他return語句。

因此,通過恢復返回語句,返回類型推演能成功:

#include <iostream> 

int main() { 
    auto append = [](auto &&cnt, auto &&me, 
        auto &&a, auto &&p1, auto &&...p) -> decltype(auto) 
    { 
     if(sizeof...(p) <= cnt) 
      return a; 
     return me(++cnt, me, a << p1, p..., 0); 
    }; 
    append(0u, append, std::cout, 1, 2, 3, 4); 
} 

Live example

+1

更改它例如到'sizeof ...(p)+ 1'來按照預期得到輸出'1234'。 – dyp

+0

爲什麼評論你自己的答案,而不是編輯? – TemplateRex

+0

@TemplateRex編輯有副作用,所以我有時會發表評論,如果這是一個小問題。 – dyp

2

我的猜測是它會一直循環嘗試推斷你的返回類型。當它看到return me(...)時,它試圖找出那個函數的返回值是什麼,這也是auto,它需要弄清楚return me(...)是什麼等等。

也許嘗試

if(sizeof...(p) <= cnt) return a; 
return me(++cnt, me, a << p1, p..., 0); 

或嘗試decltype(a)作爲返回類型。

我現在沒有1y編譯器,或者我可以肯定地說。

+0

http://coliru.stacked-crooked.com/支持Clang 3.5 SVN – TemplateRex

+0

@TemplateRex當我在工作中,我很幸運所以通過防火牆=/ – KitsuneYMG