0

在下面的代碼中,我想實現特定類型定義的二元運算符鏈接效果,我想使用 - 對於平凡的運算符鏈接,二元運算符返回相同類型的對象,大多數情況下只是簡單地返回*this,它可以平均再次用於鏈接相同類型的下一個對象。然而,就我而言,二元運算符將兩個相同類型對象(awaitable<T>::ref)的兩個reference_wrappers作爲輸入,並返回類型爲(awaitable<awaitable<T>::ref>)的聚合對象,並且我想使用返回的聚合對象來鏈接接下來awaitable<T>::ref並再次返回awaitable<awaitable<T>::ref>類型的進一步彙總對象 - 注意,無論發生多少鏈接,返回的對象始終是awaitable<awaitable<T>::ref>的相同類型。C++ 11/14模板模板參數重載的朋友操作符

模板模板參數定義在位置(XXX)的朋友操作符希望能達到此目的,但編譯器似乎不願意執行綁定。

任何人都可以闡明我如何實現所述的結果?

謝謝!

#include <functional> 

template <typename T> 
struct awaitable 
{ 
    typedef std::reference_wrapper<awaitable> ref; 

    // (A) - okay 
    friend awaitable<ref> operator||(ref a1, ref a2) 
    { 
     awaitable<ref> r; 
     return r; 
    } 

    // (XXX) - this doesn't bind 
    template < template <typename> class _awaitable > 
    friend awaitable<ref> operator||(typename awaitable<typename _awaitable<T>::ref>::ref a1, ref a2) 
    { 
     awaitable<ref> r; 
     return r; 
    } 
}; 

int main(int argc, const char * argv[]) 
{ 
    awaitable<void> a1; 
    awaitable<void> a2; 
    auto r1 = a1 || a2; // Okay - r1 is of type awaitable<awaitable<void>::ref> 

    awaitable<void> a3; 
    auto r3 = r1 || a3; // doesn't bind to the operator defined at XXX 

    return 0; 
} 

[編輯] -

答案在this崗位和this似乎說明情況非常好聽,但對我來說,朋友經營者有一個模板,模板參數(這是需要避免重複模板實例化),這可能會阻止編譯器在模板實例化時生成正確的名稱空間作用域函數?

+0

對不起,我的編輯,我試圖簡化代碼並儘可能消除任何可能的混淆,並希望上面的代碼應該非常簡單易讀(根本不需要向下滾動!) – Dejavu

+0

注意:輸入對象都是reference_wrapper包裝的,我特別不想複製發生,並在真正的代碼中,複製構造函數被刪除 – Dejavu

回答

0

似乎與模板的模板參數友元函數模板,使扣失敗。解決的辦法是友元函數定義中刪除模板的模板參數,並展開::裁判使用到std ::的reference_wrapper:

#include <functional> 

template <typename T> 
struct awaitable 
{ 
    typedef std::reference_wrapper<awaitable> ref; 

    // (A) - okay 
    friend awaitable<ref> operator||(ref a1, ref a2) 
    { 
     awaitable<ref> r; 
     return r; 
    } 

    // (XXX) - removing the template template parameter makes the template instantiation for a specific type T to generate a namespace version of the function! 
    friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<T>>>> a1, ref a2) 
    { 
     awaitable<ref> r; 
     return r; 
    } 
}; 

// template <typename T> 
// awaitable<typename awaitable<T>::ref> operator||(typename awaitable<typename awaitable<T>::ref>::ref a1, typename awaitable<T>::ref a2) 
// { 
//  awaitable<typename awaitable<T>::ref> r; 
//  return r; 
// } 

int main(int argc, const char * argv[]) 
{ 
    awaitable<void> a1; 
    awaitable<void> a2; 
    auto r1 = a1 || a2; // Okay - r1 is of type awaitable<awaitable<void>::ref> 

    awaitable<void> a3; 
    auto r3 = r1 || a3; // now it works! 

    return 0; 
} 

演示here

0

這是你所需要的?

template < template <typename> class _awaitable, typename U > 
friend auto operator||(_awaitable<std::reference_wrapper<U>> a1, ref a2) 
{ 
    awaitable<ref> r; 
    return r; 
} 

live demo

EDIT1

我看見你的答案在你刪除模板參數得到它的工作。如果void是唯一使用的類型,那麼這很好。如果你嘗試使用另一種類型,它會失敗。我必須解決的最近的問題是使用std :: ref(r1)

template<typename U> 
friend awaitable<ref> operator||(std::reference_wrapper<awaitable<std::reference_wrapper<awaitable<U>>>> a1, ref a2) 
{ 
    std::cout << "(XXX2)" << std::endl; 
    awaitable<ref> r; 
    return r; 
} 

awaitable<int> a4; 
auto r4 = std::ref(r1) || a4; 

live demo 2

+0

不。您在_awaitable之後缺少a :: ref,請參閱:http://coliru.stacked-crooked。com/a/ed848c7f0098741d – Dejavu

+0

但那不是你在or'ing,你正在呼叫r1 || a3 - > awaitable >> ||等待

+0

我想將對象隱式轉換爲第一個定義工作的ref版本,我想知道爲什麼XXX不是 – Dejavu