![](/img/trans.png)
[英]Redefinition error when defining friend function inside class template
[英]Friend operator in template struct raises redefinition error
考慮以下代碼:
template<typename T,typename K>
struct A{
friend std::ostream& operator<<(std::ostream& out, K x) {
// Do some output
return out;
}
};
int main(){
A<int,int> i;
A<double,int> j;
}
它不編譯,因為A的兩個實例化實例化operator<<
兩次具有相同的簽名,所以我收到此錯誤:
test.cpp:26:25: error: redefinition of ‘std::ostream& operator<<(std::ostream&, int)’
friend std::ostream& operator<<(std::ostream& out, K x) { return out; }
^
test.cpp:26:25: error: ‘std::ostream& operator<<(std::ostream&, int)’ previously defined here
如何解決這個問題? 如果該運算符可能具有兩個不同實例的相同簽名,那么如何在模板中擁有友元運算符? 如何在不觸發重新定義錯誤的情況下解決此問題?
我覺得在宣布這樣的朋友時沒有任何用處,不過這就是你如何做到的:
template<typename T, typename K>
struct A{
template<typename L>
friend std::ostream& operator<<(std::ostream& out, L const &x);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, T const &x) {
// ...
return out;
}
編輯:
另一種選擇可能更接近你想要的是:
template<typename T>
std::ostream& operator<<(std::ostream& out, T const &x);
template<typename T, typename K>
struct A{
friend std::ostream& operator<<<K>(std::ostream& out, K const &x);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, T const &x) {
// ...
return out;
}
但是真的不確定你為什么要這樣。 恕我直言,你的設計有嚴重的缺陷。
您的問題以下列方式出錯。
假設它是一個存根,你的類有一些私有的東西,它需要聲明一個朋友,這樣做的目的是朋友是類本身的外部,但可以訪問其中的私有。
在您的情況下,您將參數的流功能聲明為朋友。 那也行。 這意味着如果有人創建了一個類Bar
並且想要定義一個Bar
如何流式傳輸,那么它們的實現可以訪問任何類型T
A<T,Bar>
中的任何內容。
模板與operator<<( ostream&, int)
的沖突實際上並不是問題,因為編譯器知道要選擇哪一個。 它總是會選擇非模板化的精確匹配。 你的問題是你有兩個模板化的,編譯器不能在它們之間進行選擇,因為它們都是同等有效的。
也許這樣的事情是你真正想要實現的目標
template< typename X, typename Y >
struct A
{
friend void a_print( std::ostream& Y const & ); // foo external function with Y as parameter, can access this
};
std::ostream & operator<<( std::ostream & out, Bar const& bar )
{
a_print( out, bar );
return out;
}
void a_print( Bar const& bar, std::ostream & out )
{
// implement and call private members of A<Foo, Bar>
return out;
}
您可以將流模板設為朋友,並使用特定實現實現Bar的流式傳輸。
將方法分解為基類:
template <typename K>
struct ABase
{
friend std::ostream& operator<<(std::ostream& out, K x) {
// Do some output
return out;
}
};
template <typename T,typename K>
struct A : public ABase<K>
{};
如果要流式傳輸A
對象,則應該使用正確的簽名
template<typename T,typename K>
struct A{
friend std::ostream& operator<<(std::ostream& out, const A& x) {
// Do some output
return out;
}
};
拿A<T,K>
你可以訪問私人會員,而不是K
如果沒有辦法從K獲得A(並且如果K
是int
則不能),使<<(ostream&,K)
成為A
的朋友沒有任何好處。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.