类模板专门化的操作符重载

operator overloading for a class template specialization

本文关键字:操作符 重载 专门化      更新时间:2023-10-16

我在这里遇到了一个令人困惑的问题,到目前为止我找不到任何解决方案:链接器抱怨重载非成员操作符==的多重定义。想象一下下面的情况:

template <class T>
struct MyPtr
{
  T* val;
  ...
}
template <class T> bool operator==(MyPtr<T> const & lhs, MyPtr<T> const & rhs)
{ return *lhs.val == *rhs.val; }
template <class T> bool operator==(MyPtr<T> const & lhs, T* const & rhs)
{ return *lhs.val == *rhs;}

到目前为止一切都很好,一切都像一个魅力,但当我试图专门化我的类以特定的方式对char*作出反应时,事情变得奇怪:

template <>
struct MyPtr<char>
{
  char* val;
  ...
}
//Now each of these functions result in a multiple definition error of the Linker, 
//and i dont get why:
//bool operator== (MyPtr<char> const& lhs, MyPtr<char> const& rhs)
//{ return strcmp(lhs.val,rhs.val) == 0;}
//template <> bool operator==<char> (MyPtr<char> const& lhs, MyPtr<char> const& rhs)
//{ return strcmp(lhs.val,rhs.val) == 0;}

我在这里做错了什么?我的代码中的顺序就像这里写的那样。将这些函数定义移到Class专门化之上会导致错误:

Error : specialization of 'MyPtr<char>' after instantiation
Error : redefinition of 'class MyPtr<char>'

请注意我必须使用GCC 4.1.2。我希望这不是编译器的问题…再次…

函数定义只能出现在头文件中

  • 已使用inline关键字OR
  • 声明
  • 在类定义中定义,OR
  • 至少包含一个模板参数

(这些都是适用ODR的多重相同定义版本的情况。)

所以模板函数通常不需要inline。但是显式特化实际上没有任何模板参数,所以如果你想在头文件中使用它,你应该将其标记为inline

template <> bool operator==<char> (MyPtr<char> const& lhs, MyPtr<char> const& rhs)
{ return strcmp(lhs.val,rhs.val) == 0;}

template <> bool operator==<char> (MyPtr<char> const& lhs, char* const& rhs)
{ return strcmp(lhs.val,rhs) == 0;}

?

感谢jogojapan的更正