2016-09-24 63 views
3

考慮下面的代碼片段工作完全正常:模板友元函數的轉發聲明

class A 
{ 
private: 
    int d; 
public: 
    A(int n){ d = n;} 
    friend int foo(A a); 
}; 

int foo(A a) 
{ 
    return a.d; 
} 

然而,當我嘗試使用模板類,我需要轉發聲明友元函數爲它運行,如下所示:

template <typename T> 
class B; 

template <typename T> 
T foof(B<T> a); 


template <typename T> 
class B 
{ 
private: 
    T d; 
public: 
    B(T n){ d = n;} 
    friend T foof<>(B<T> a); 
}; 

template <typename T> 
T foof(B<T> a) 
{ 
    return a.d; 
} 

爲什麼向前聲明需要在第二個例子中,但不是在第一個?另外,爲什麼我必須將<>放入B類內的foof聲明中?爲什麼它不足以在模板中聲明?我想了解這些工作是如何工作的,以便在我需要使用它時不必盲目記住這種代碼。

感謝

回答

3

這是因爲

friend int foo(A a); 

是函數聲明,並在同一時間的朋友,但:

friend T foof<>(B<T> a); 

是朋友申報模板實例。那不一樣。實例化不會聲明模板函數。


你可以結交整體功能模板,則不需要向前聲明:

template <typename T> 
class B 
{ 
private: 
    T d; 
public: 
    B(T n){ d = n;} 
    template<class U> 
    friend U foof(B<U> a); 
}; 
+0

注意:後者有潛在的意外後果。它說,對於任何給定的'T',我們正在友好* foof'的所有*實例化,無論'T'是否是模板參數。總之,'int fo (B );'是'B '的朋友。在採用焦土焦域方法之前,請考慮這是否是一個問題 - 如何使模板函數(或類)的所有實例化。 – WhozCraig

2

爲什麼向前聲明需要在第二個例子中,但不是在第一個?

因爲在語法上第二個不是可以用來聲明函數的形式,但是第一個是。

此外,爲什麼我必須把<>放在B類的foof聲明中?爲什麼它不足以在模板中聲明?

您表示您正在爲功能模板的專業化發展,而不是爲不是模板的功能添加功能,而這正是它的意思。您可以擁有類模板的非模板好友功能。