2017-01-23 26 views
0

我有一個函數,砍伐,看起來像:遞歸迭代,而無需重新綁定參考

// bar is basically a linked list with extra stuff tagged on 
void recurses(std::unique_ptr<bar> & P) 
{ 
    bool ok = decide_if_this_P_is_acceptable(P); 
    if (!ok) 
    { 
    recurses(P->getNextPtr()); 
    return; 
    } 
    // Now do lots more stuff involving the reference P and P.reset() 
} 

酒吧類暴露了一個名爲getNextPtr()方法,它返回一個std::unique_ptr<bar>&然後可以通過回遞歸。

不幸的是,這個堆棧可能會導致一些大的輸入。我想將它轉換爲迭代,例如

void recurses(std::unique_ptr<bar> & P) 
{ 
    bar * N = nullptr; 
    for (;;) 
    { 
    bool ok = decide_if_this_P_is_acceptable(P); 
    if (ok) 
    { 
     break; 
    } 
    P = P->getNextPtr(); 
    } 
    // P is now OK 
    // Now do lots more stuff involving the reference P and P.reset() 
} 

這當然拒絕編譯,因爲我們不能重新綁定引用(std::unique_ptr<bar> & P)。

如何讓功能的其餘部分發生變異,而不管哪個參考被認爲是好的,我該如何失去遞歸?

+1

爲什麼沒有得到來自'P'原始指針,並與工作? –

+1

我不清楚你想要的返回語義。你的遞歸版本試圖返回遞歸調用的結果 - 它有一個無返回值的基本情況 - 並且函數類型是** void **。這個回報聲明應該只是一個沒有轉讓的呼叫嗎? – Prune

+0

什麼是'std :: unique_ptr :: getNextPtr'? – user2079303

回答

4

最簡單的解決方案是使用std::reference_wrapper而不是原始參考。這是rebindable:

void recurses(std::reference_wrapper<std::unique_ptr<bar>>& P) 
{ 
    bar * N = nullptr; 
    for (;;) 
    { 
    bool ok = decide_if_this_P_is_acceptable(P); 
    if (ok) 
    { 
     break; 
    } 
    P = P.get().getNextPtr(); 
    } 
    // P is now OK 
    // Now do lots more stuff involving the reference P and P.reset() 
} 

注意額外.get().getNextPtr()呼叫,它首先訪問底層的引用之前。您必須在所有成員函數調用中都這樣做。

或者,你可以只使用一個指針內部:

void recurses(std::unique_ptr<bar>& R) 
{ 
    std::unique_ptr<bar>* P = &R; 

    bar * N = nullptr; 
    for (;;) 
    { 
    bool ok = decide_if_this_P_is_acceptable(*P); 
    if (ok) 
    { 
     break; 
    } 
    P = &P->getNextPtr(); 
    } 
    // P is now OK 
    // Now do lots more stuff involving the reference P and P.reset() 
} 
+0

'while(!decide_if_this_P_is_acceptable(* P))'is more more簡潔的循環 – Caleth

+0

unique_ptr *可能是更明顯的答案,我會隨之去做。謝謝 –