2012-10-09 32 views
7

我對C++中特定模板友誼有疑問。書中C++入門 ,具體的模板友誼是這樣寫的:C++中的特定模板友誼

template <class T> class Foo3; 
template <class T> void templ_fcn3(const T&); 
template <class Type> class Bar { 
    // each instantiation of Bar grants access to the 
    // version of Foo3 or templ_fcn3 instantiated with the same type 
    friend class Foo3<Type>; 
    friend void templ_fcn3<Type>(const Type&); 
    // ... 
}; 

特殊的一點是,有

<Type> 

朋友聲明的類或函數名後。

然而,在實踐中,如果我這樣寫:

template <class Type> class T_CheckPointer; 
template <class T> T_CheckPointer<T> operator+(const T_CheckPointer<T> &, const size_t n); 

template <typename Type> 
class T_CheckPointer { 

    // Specific Template Friendship 
    friend T_CheckPointer<Type> 
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n); 

// other code... 

} 

將有實例爲模板函數時的錯誤。

如果我在函數名後刪除字改變

// Specific Template Friendship 
friend T_CheckPointer<Type> 
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n); 

// Specific Template Friendship 
friend T_CheckPointer<Type> 
    operator+ <> (const T_CheckPointer<Type> &, const size_t n); 

,然後一切都會好起來的。

任何人都可以告訴我原因嗎?


的信息,還有就是錯誤信息當我打電話

int iarr[] = {1, 2, 3, 4}; 
T_CheckPointer<int> itcp(iarr, iarr+4); 

錯誤消息:

/usr/include/c++/4.4/bits/stl_iterator_base_types.h: In instantiation of ‘std::iterator_traits<int>’: 
/usr/include/c++/4.4/bits/stl_iterator.h:96: instantiated from ‘std::reverse_iterator<int>’ 
../Classes/T_CheckPointer.hpp:31: instantiated from ‘T_CheckPointer<int>’ 
../PE16.cpp:520: instantiated from here 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:127: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:128: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:129: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:130: error: ‘int’ is not a class, struct, or union type 
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:131: error: ‘int’ is not a class, struct, or union type 
+0

什麼是錯誤信息? – enobayram

+0

@enobayram,感謝您的關注,我把它們放在文章中。 – Tianyi

+0

你能提供一個**最小**的例子(例如編譯)。Ideone)顯示問題?你有沒有嘗試升級到GCC 4.7? – TemplateRex

回答

4

這裏有一個小例子:

template<typename T> struct U { typedef typename T::X X; }; 
template<typename T> void foo(typename U<T>::X); 

template<typename T> struct S; 
template<typename T> void foo(S<T>); 
template<typename T> struct S { friend void foo<T>(S<T>); }; 

template struct S<int>; 

聲明失敗的原因是,通過提供模板參數的完整列表,您正在請求編譯器專門化所有可用的函數模板,並選擇與簽名最匹配的模板參數。 foo的第一個定義的專門化會導致U的專門化,並導致形式不健全的程序。

相反,如果你省略模板參數,它會從參數推斷。作爲這種模板參數推導根據14.8.2 [temp.deduct]進行,並且特別適用14.8.2p8,這意味着,在U專業化的取代失敗不是錯誤(SFINAE)。

這是一個很好的理由省略模板參數任何地方,他們可以從上下文(例如這裏的功能或操作參數類型)來推斷。請注意,您仍然需要提供<>括號以確保operator +被讀爲模板ID14.5.4 [temp.friend])。

+0

+1這真是一個很好的答案!還要注意''括號'是爲了防止選擇非模板函數而不是模板函數。請參閱Herb Sutter的舊專欄http://www.drdobbs.com/befriending-templates/184403853 – TemplateRex

+0

+1非常感謝您的回覆!你的回答非常明確。 @ecatmur – Tianyi