模板运算符重载类头之外的实现

Int*_*rca 5 c++ templates operator-overloading friend

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

谢谢,


工作

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

不工作

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

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

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

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

bool operator ==(const Rect<T> &a, const Rect<T> &b);
bool operator !=(const Rect<T> &a, const Rect<T> &b);
Run Code Online (Sandbox Code Playgroud)

如果您还定义了函数模板

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

并呼吁他们在你的代码,然后将其命名查询和参数推导进行无困难,但函数重载决议将在领带是由非模板类友元函数断头.但是,如果没有定义这些,您的程序将无法链接.

有两个转义:在类中定义运算符(如您已提供的那样)或(再次由@AndyProwl提及)使用此peculair语法与类中的通用运算符模板建立伙伴关系

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

请注意,与Herb Sutter的旧专栏中解释说,交友模板是一项棘手的工作.