簡體   English   中英

模板結構中的Friend運算符會引發重定義錯誤

[英]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(並且如果Kint則不能),使<<(ostream&,K)成為A的朋友沒有任何好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM