2013-12-22 36 views
0

我想用友元函數定義模板結構,其中的參數類型是從結構中定義的類型派生的。如果相應的結構已經實例化,那麼friend函數應該可以被調用而不需要顯式的類型說明。模板結構的好友功能,參數類型取決於結構的內部結構

以下方法似乎工作:

template <typename T> struct A { 
    typedef T const& underlying_param_type; 
    typedef A<T>& param_type; 
    friend void mutateA(param_type a, underlying_param_type b) { a.data_ = b; } 
    T data_; 
}; 

如果一個定義了參數類型的友元函數不依賴於它可能如下分離接口和實現結構的內部:

template <typename T> struct B; 
template <typename T> void mutateB(B<T>& a, T const& b); 

template <typename T> struct B { 
    friend void mutateB <> (B<T>& a, T const& b); 
    T data_; 
}; 

template <typename T> void mutateB(B<T>& a, T const& b) { a.data_ = b; } 

現在我想知道兩種方法是否可以結合使用。下面的方法是行不通的(鐺++ 3.3,G ++ 4.8.2,-std = C++ 11):

template <typename T> struct C; 
template <typename T> void mutateC(typename C<T>::param_type a, typename C<T>::underlying_param_type b); 

template <typename T> struct C { 
    typedef T const& underlying_param_type; 
    typedef C<T>& param_type; 
    friend void mutateC <> (typename C<T>::param_type a, typename C<T>::underlying_param_type b); 
    T data_; 
}; 

template <typename T> void mutateC(typename C<T>::param_type a, typename C<T>::underlying_param_type b) { a.data_ = b; } 

int main() { 
    A<int> a; 
    mutateA(a, 1); 

    B<int> b; 
    mutateB(b, 1); 

    C<int> c; // error: no function template matches function template specialization 'mutateC' 
    mutateC(c, 1); 

    return 0; 
} 

我想這最後的方法,因爲模板參數推導無法跨::工作失敗。有任何想法嗎?

+0

'<>''成'?也許更多,但你的問題看起來像你的朋友聲明中的語法錯誤。從一個更簡單的朋友聲明開始,讓它起作用? (你的朋友是哪個專業的) – Yakk

+0

把<>改成後陳述爲C c;編譯但mutateC(c,1)不。 mutateC (c,1)在此設置下工作,但這不足以滿足我的使用情況。 – precarious

+0

啊是的。對於任意'typedef',你所要求的需要顛倒turing完整的計算,所以是不可行的。提供更多細節,因爲特殊情況可能是可行的。作爲你的第一個作品的原因是,ADL找到了「A 」論點的朋友作爲例子。在您的非workimg示例中傳遞的類型不會幫助ADL,爲此,您需要反轉所有類型的'template'替換。您編寫的手動反轉可以通過輔助函數完成。 – Yakk

回答

0

添加一個間接層來解決該問題:

template <typename T> struct C; 
template <typename T> void mutateC_impl(typename C<T>::param_type a, typename C<T>::underlying_param_type b); 

template <typename T> struct C { 
    typedef T const& underlying_param_type; 
    typedef C<T>& param_type; 
    friend void mutateC(typename C<T>::param_type a, typename C<T>::underlying_param_type b) { mutateC_impl<T>(a, b); } 
    friend void mutateC_impl<T>(typename C<T>::param_type a, typename C<T>::underlying_param_type b); 
    private: T data_; 
}; 

template <typename T> void mutateC_impl(typename C<T>::param_type a, typename C<T>::underlying_param_type b) { a.data_ = b; } 
1

讓兩個小的變化:

  • 朋友虛空mutateC ...
  • mutateC < int>的(C,1);
+0

謝謝。 「如果相應的結構已經被實例化,朋友函數應該可以被調用而不需要顯式的類型說明。」 – precarious