C++ 重载友元运算符<&书信电报;对于模板类

C++ 重载友元运算符<&书信电报;对于模板类,c++,templates,operator-overloading,friend,ostream,C++,Templates,Operator Overloading,Friend,Ostream,我已经在StackOverflow.com上读到了几个关于我的问题的问题,但似乎并没有一个能解决我的问题。或者我可能做错了。。。 如果我将重载的b) 返回a; 其他的 返回b; } 模板 D类 { 公众: D(进修班) :d(in){}; 布尔运算符>(常数D和rhs)常数; classT运算符=(常数D和rhs); friend ostream&operator您不能像那样声明朋友,您需要为其指定不同的模板类型 template <typename SclassT> friend

我已经在StackOverflow.com上读到了几个关于我的问题的问题,但似乎并没有一个能解决我的问题。或者我可能做错了。。。 如果我将重载的
b)
返回a;
其他的
返回b;
}
模板
D类
{
公众:
D(进修班)
:d(in){};
布尔运算符>(常数D和rhs)常数;
classT运算符=(常数D和rhs);

friend ostream&operator您不能像那样声明朋友,您需要为其指定不同的模板类型

template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);

你不能像那样声明一个朋友,你需要为它指定一个不同的模板类型

template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);

这在没有任何编译器警告的情况下对我有效

#include <iostream>
using namespace std;

template <class T>
T my_max(T a, T b)
{
  if(a > b)
    return a;
  else
    return b;
}

template <class classT>
class D
{
public:
  D(classT in)
    : d(in) {};

  bool operator>(const D& rhs) const {
    return (d > rhs.d);
  }

  classT operator=(const D<classT>& rhs);

  friend ostream& operator<< (ostream & os, const D& rhs) {
    os << rhs.d;
    return os;
  }

private:
  classT d;
};


int main()
{

  int i1 = 1;
  int i2 = 2;
  D<int> d1(i1);
  D<int> d2(i2);

  cout << my_max(d1,d2) << endl;
  return 0;
}
#包括
使用名称空间std;
模板
T my_max(T a,T b)
{
如果(a>b)
返回a;
其他的
返回b;
}
模板
D类
{
公众:
D(进修班)
:d(in){};
布尔运算符>(常数D和rhs)常数{
返回(d>rhs.d);
}
classT运算符=(常数D和rhs);

friend ostream&operator这在没有任何编译器警告的情况下对我有效

#include <iostream>
using namespace std;

template <class T>
T my_max(T a, T b)
{
  if(a > b)
    return a;
  else
    return b;
}

template <class classT>
class D
{
public:
  D(classT in)
    : d(in) {};

  bool operator>(const D& rhs) const {
    return (d > rhs.d);
  }

  classT operator=(const D<classT>& rhs);

  friend ostream& operator<< (ostream & os, const D& rhs) {
    os << rhs.d;
    return os;
  }

private:
  classT d;
};


int main()
{

  int i1 = 1;
  int i2 = 2;
  D<int> d1(i1);
  D<int> d2(i2);

  cout << my_max(d1,d2) << endl;
  return 0;
}
#包括
使用名称空间std;
模板
T my_max(T a,T b)
{
如果(a>b)
返回a;
其他的
返回b;
}
模板
D类
{
公众:
D(进修班)
:d(in){};
布尔运算符>(常数D和rhs)常数{
返回(d>rhs.d);
}
classT运算符=(常数D和rhs);
friend ostream&operator给你:

#include <cstdlib>
#include <iostream>
using namespace std;

template <class T>
T my_max(T a, T b)
{
   if(a > b)      
      return a;
   else
      return b;
}

template <class classT>
class D
{
public:
   D(classT in)
      : d(in) {};
   bool operator>(const D& rhs) const { return d > rhs.d;};
   classT operator=(const D<classT>& rhs);

   template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
   classT d;
};

template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
    os << rhs.d;
    return os;
}


int main()
{

   int i1 = 1;
   int i2 = 2;
   D<int> d1(i1);
   D<int> d2(i2);

   cout << my_max(d1,d2) << endl;
   return 0;
}
#包括
#包括
使用名称空间std;
模板
T my_max(T a,T b)
{
如果(a>b)
返回a;
其他的
返回b;
}
模板
D类
{
公众:
D(进修班)
:d(in){};
布尔运算符>(const D&rhs)const{return D>rhs.D;};
classT运算符=(常数D和rhs);
模板朋友ostream&operator给你:

#include <cstdlib>
#include <iostream>
using namespace std;

template <class T>
T my_max(T a, T b)
{
   if(a > b)      
      return a;
   else
      return b;
}

template <class classT>
class D
{
public:
   D(classT in)
      : d(in) {};
   bool operator>(const D& rhs) const { return d > rhs.d;};
   classT operator=(const D<classT>& rhs);

   template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
   classT d;
};

template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
    os << rhs.d;
    return os;
}


int main()
{

   int i1 = 1;
   int i2 = 2;
   D<int> d1(i1);
   D<int> d2(i2);

   cout << my_max(d1,d2) << endl;
   return 0;
}
#包括
#包括
使用名称空间std;
模板
T my_max(T a,T b)
{
如果(a>b)
返回a;
其他的
返回b;
}
模板
D类
{
公众:
D(进修班)
:d(in){};
布尔运算符>(const D&rhs)const{return D>rhs.D;};
classT运算符=(常数D和rhs);

模板朋友ostream&operator我认为你首先不应该交朋友

您可以创建一个公共方法调用print,如下所示(对于非模板类):

std::ostream&MyClass::print(std::ostream&os)常量
{

我认为你首先不应该交朋友

您可以创建一个公共方法调用print,如下所示(对于非模板类):

std::ostream&MyClass::print(std::ostream&os)常量
{

os这是一个常见的问题,它们有不同的方法,这些方法相似,但实际上并不相同。这三种方法的不同之处在于,你宣布谁是你函数的朋友,以及你如何实现它

外向的人


将模板的所有实例化声明为好友。这是您已接受的答案,也是大多数其他答案的建议。在这种方法中,您无需通过声明friends all
operator来打开您的特定实例化
D
。这是具有不同答案的常见问题之一这三种方法在声明谁是函数的朋友以及如何实现函数方面有所不同

外向的人


将模板的所有实例化声明为friends。这是您接受的答案,也是大多数其他答案的建议。在这种方法中,您不需要通过声明friends all
运算符来打开特定的实例化
D
。最近有一个关于这一点的问题可能很有启发性:@Daniel-这并没有解决我在模板类重载时遇到的问题。我认为如果不使用给定答案修改问题会更好。这会使确定原始问题变得更困难。您可能希望在最后添加一个编辑,以解决问题的更改,但当问题变为显性时,我会感到困惑ime和我必须调出历史记录,看看一开始到底问了什么。最近有一个关于这个问题的问题可能很有启发性:@Daniel-它没有解决我在重载模板类时遇到的问题。我认为如果你不使用给定的答案修改问题会更好。这会让你更难确定ine最初的问题是什么。你可能想在最后添加一个编辑,修改后解决了问题,但我发现当问题超时更改时,我会感到困惑,我必须调出历史记录来查看最初实际被问到的问题。是的,我已经这样做了,但是如果我不想要
operator@starcorn:小麦她将方法/函数标记为内联(隐式或显式)与函数是否真的内联在代码中几乎没有关系。因此,这是一个毫无意义的担忧。+1。@starcorn:这个解决方案比公认的解决方案要好。区别很微妙,但在公认的答案中,您声明了所有实例化
operator@starcorn当前位置我添加了一个答案,试图消除三种不同方法的差异是的,我已经这样做了,但是如果我
std::ostream& operator<<(std::ostream& os, const MyClass& myClass)
{
  return myClass.print(os);
}
template <typename T>
class Test {
   template <typename U>      // all instantiations of this template are my friends
   friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
   // Can access all Test<int>, Test<double>... regardless of what T is
}
template <typename T>
class Test {
   friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
      // can access the enclosing Test. If T is int, it cannot access Test<double>
   }
};
// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );

// Declare the actual templates:
template <typename T>
class Test {
   friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
   // Can only access Test<T> for the same T as is instantiating, that is:
   // if T is int, this template cannot access Test<double>, Test<char> ...
}
namespace hacker {
   struct unique {}; // Create a new unique type to avoid breaking ODR
   template <> 
   std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
   {
      // if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
      // if Test<T> is an introvert, then I can only mess up with Test<unique> 
      // which is just not so much fun...
   }
}