模板结构中的Friend运算符会引发重定义错误

gex*_*ide 4 c++ templates operator-overloading c++11

考虑以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

它没有编译,因为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
Run Code Online (Sandbox Code Playgroud)

如何解决这个问题?如果该运算符可能具有两个不同实例的相同签名,那么如何在模板中拥有友元运算符?如何在不触发重新定义错误的情况下解决此问题?

101*_*010 5

我觉得在宣布这样的朋友时没有任何用处,不过这是你可以做到的:

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;
}
Run Code Online (Sandbox Code Playgroud)

LIVE DEMO

编辑:

另一种选择可能更接近你想要的是:

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;
}
Run Code Online (Sandbox Code Playgroud)

LIVE DEMO

但是真的不确定你为什么要这样.恕我直言,你的设计有严重的缺陷.


ere*_*non 2

将方法分解为基类:

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>
{};
Run Code Online (Sandbox Code Playgroud)