5

'util.h' 中定义的以下代码编译和链接。但是,当我将运算符重载的实现移到“util.cc”中时,链接器无法解析符号。这是可能的,还是由于模板的性质而不能这样做?

谢谢,


在职的

实用程序.h

template<class T>
struct Rect {
  T x, y, w, h;

  friend bool operator ==(const Rect<T> &a, const Rect<T> &b) {
    return (a.x == b.x && a.y == b.y && a.w == b.w && a.h == b.h);
  }

  friend bool operator !=(const Rect<T> &a, const Rect<T> &b) {
    return !(a == b);
  }
};

不工作

实用程序.h

template<class T>
struct Rect {
  T x, y, w, h;

  friend bool operator ==(const Rect<T> &a, const Rect<T> &b);
  friend bool operator !=(const Rect<T> &a, const Rect<T> &b);
};

实用程序.cc

template<class T>
bool operator ==(const Rect<T> &a, const Rect<T> &b)
{
    return (a.x == b.x && a.y == b.y && a.w == b.w && a.h == b.h);
}

template<class T>
bool operator !=(const Rect<T> &a, const Rect<T> &b)
{
    return !(a == b);
}
4

1 回答 1

6

由于@AndyProwl链接中解释的原因,您的实际问题的答案是否定的,即使您将运算符定义包含在标题util.h中,答案仍然是否定的。

原因是这些运算符实际上是非模板函数,它们被注入到它们被定义的类的封闭范围中,作为类模板实例化的副作用。换句话说,这个类模板

template<class T>
struct Rect {
  T x, y, w, h;

  friend bool operator ==(const Rect<T> &a, const Rect<T> &b);
  friend bool operator !=(const Rect<T> &a, const Rect<T> &b);
};

为每种类型生成以下两个非模板函数T

bool operator ==(const Rect<T> &a, const Rect<T> &b);
bool operator !=(const Rect<T> &a, const Rect<T> &b);

如果您还定义了函数模板

template<class T>
bool operator ==(const Rect<T> &a, const Rect<T> &b)
{
    return (a.x == b.x && a.y == b.y && a.w == b.w && a.h == b.h);
}

template<class T>
bool operator !=(const Rect<T> &a, const Rect<T> &b)
{
    return !(a == b);
}

并在您的代码中调用它们,然后名称查找和参数推导毫无困难地继续进行,但函数重载决议将以平局结束,该平局被非模板类内友函数打破。但是当这些没有定义时,你的程序将无法链接

There are two escapes: define the operators in-class (as you already provided) or (again as alluded to by @AndyProwl) to befriend the general operator templates inside the class with this peculair syntax

// forward declarations
template<typename T> struct Rect;
template<typename T> bool operator==(const Rect<T>&, const Rect<T>&);
template<typename T> bool operator!=(const Rect<T>&, const Rect<T>&);

template<class T>
struct Rect {
  T x, y, w, h;

  // friend of operator templates
  friend bool operator == <>(const Rect<T> &a, const Rect<T> &b);
  friend bool operator != <>(const Rect<T> &a, const Rect<T> &b);
};

// definitions of operator templates follow

Note that befriending templates is a tricky business, as explained in this old column by Herb Sutter.

于 2013-03-31T00:12:11.520 回答