2012-11-19 90 views
3

我正在閱讀litb對問題here的回答,他詳細說明了如何創建類模板的專用朋友函數。類模板的朋友函數的明確專業化

我試圖創建一個典範,其做他認爲正是(代碼末):

// use '<>' to specialize the function template with the class template's type 
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f) 

這導致編譯器錯誤

error: defining explicit specialization ‘operator<< <>’ in friend declaration 

顯式聲明專業化中的模板參數不起作用:

friend std::ostream& operator<< <T>(std::ostream& os, const foo<T>& f) // same error 

在另一方面,從使用專門使用友元函數模板代替改變確實工作:

template<typename U> 
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works 

所以我的問題是:

  • 是什麼原因造成第一錯誤?
  • 我怎樣才能明確專門化ostream operator周圍的類模板專業化?

的Exemplar下面的代碼:

#include <iostream> 

// fwd declarations 
template<typename T> struct foo; 
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&); 

template<typename T> 
struct foo 
{ 
    foo(T val) 
     : _val(val) 
    {} 

    friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f) // error line 
    //template<typename U> 
    //friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works 
    { 
     return os << "val=" << f._val; 
    } 

    T _val; 
}; 


int main() 
{ 
    foo<std::string> f("hello world"); 
    std::cout << f << std::endl; 
    exit(0); 
} 

回答

2

在litb的榜樣,他只是聲明專業化作爲類的朋友。他不是定義的專業化,這是你的代碼在做什麼。您不允許在類聲明(或任何非名稱空間範圍)中定義專門化。

你需要的是這樣的:

template <class T> 
class foo; 

template<class T> 
std::ostream& operator<<(std::ostream& os, const foo<T>& f) 
{ 
    return os << "val=" << f._val; 
} 

template<typename T> 
struct foo 
{ 
    // ... 
private: 
    friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f); 
    T _val; 
}; 
+0

啊 - 感謝您爲我澄清! –

+0

@lori歡迎您! – je4d

2

你有兩個選擇:

刪除FWD聲明和定義在課堂上的一切。

template <typename U> 
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works 
{ 
    return os << "val=" << f._val; 
} 

定義類以外friend函數。

template<typename T> struct foo; 
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&); 

template<typename T> 
struct foo 
{ 
    foo(T val) 
     : _val(val) 
    {} 

    friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f); 

    T _val; 
}; 

template <typename T> 
std::ostream& operator<<(std::ostream& os, const foo<T>& f) 
{ 
     return os << "val=" << f._val; 
} 
+0

定義友元函數的類的外部環境不會讓我專注於所使用的類型實例的原始類模板。 –

+0

刪除fwd聲明沒有區別 - 我仍然不能使用類模板的類型作爲friend function template的專門化。 (現在錯誤是'operator <<'作爲非函數聲明') –

+0

謝謝Jesse - 通過您的編輯,我現在可以看到您的建議。 –