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

时间:2013-03-30 23:41:29

标签: 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);
  }
};

不工作

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);
};

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);
}

1 个答案:

答案 0 :(得分:6)

对于@AndyProwl link中解释的原因,您的实际问题的答案是否定的,即使您在标题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);
}

并在你的代码中调用它们,然后名称查找和参数推导继续没有困难,但函数重载解析将以非模板类内友元函数打破的平局结束。但是,如果未定义这些内容,您的程序将无法链接

有两个转义:在类中定义运算符(如您已提供的那样)或(再次由@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

请注意,交友模板是一件棘手的事情,正如Herb Sutter在old column中所解释的那样。