Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类模板专门化的运算符重载_C++_Gcc_Operator Overloading_Template Specialization - Fatal编程技术网

C++ 类模板专门化的运算符重载

C++ 类模板专门化的运算符重载,c++,gcc,operator-overloading,template-specialization,C++,Gcc,Operator Overloading,Template Specialization,我在这里遇到了一个令人困惑的问题,到目前为止我找不到任何解决方案: 链接器抱怨重载的非成员运算符==的多重定义。 想象一下以下情况: template <class T> struct MyPtr { T* val; ... } template <class T> bool operator==(MyPtr<T> const & lhs, MyPtr<T> const & rhs) { return *lhs.val =

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

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;}
模板
结构MyPtr
{
T*val;
...
}
模板布尔运算符==(MyPtr常量和lhs、MyPtr常量和rhs)
{return*lhs.val==*rhs.val;}
模板布尔运算符==(MyPtr常量和lhs、T*常量和rhs)
{return*lhs.val==*rhs;}
到目前为止,一切都像charme一样工作,但当我试图专门化我的类以特定的方式对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;}
模板
结构MyPtr
{
char*val;
...
}
//现在,每个函数都会导致链接器的多定义错误,
//我不明白为什么:
//布尔运算符==(MyPtr常量和lhs、MyPtr常量和rhs)
//{返回strcmp(lhs.val,rhs.val)==0;}
//模板布尔运算符==(MyPtr常量和lhs、MyPtr常量和rhs)
//{返回strcmp(lhs.val,rhs.val)==0;}
那么我做错了什么?我的代码中的顺序与这里写的一样。将这些函数定义移到类专用化上方会导致错误:

Error : specialization of 'MyPtr<char>' after instantiation
Error : redefinition of 'class MyPtr<char>'
错误:实例化后“MyPtr”的专门化
错误:“类MyPtr”的重新定义
请注意,我必须使用GCC 4.1.2。我希望这不是编译器的问题。。。再一次…

这不应该吗

template <> bool operator==<char> (MyPtr<char> const& lhs, MyPtr<char> const& rhs)
{ return strcmp(lhs.val,rhs.val) == 0;}
模板布尔运算符==(MyPtr常量和lhs,MyPtr常量和rhs)
{返回strcmp(lhs.val,rhs.val)==0;}

template bool操作符==(MyPtr const&lhs,char*const&rhs)
{返回strcmp(lhs.val,rhs)==0;}
?


感谢jogojapan的更正

只有在以下情况下,函数定义才会出现在头文件中:

  • 它已用
    内联
    关键字声明,或
  • 在类定义中定义,或
  • 它至少涉及一个模板参数
(ODR的多个相同定义版本适用于这些情况。)


因此,
inline
通常不需要模板函数。但是显式专门化实际上没有任何模板参数,因此如果您想在头文件中使用它,应该将其标记为
内联

操作符==
中到底在做什么?为了避免多个定义,请使用
inline
关键字。当您说“这些函数中的每一个都会导致多个定义错误”时,这是否意味着您的源代码中有两个函数,还是只有一个?显式模板专门化不太可能使用,如果您有一个接受相同参数的非模板函数。@aschepper此显式模板专门化不仅没有用,而且会导致链接器出现问题。显式专门化会导致实例化,这与非模板函数冲突。这在GCC4.7和msvc 10中可以很好地编译。两个编译器都调用函数的非模板版本。不,它们都是定义运算符的唯一方法。第一种是直接重载,而第二种是模板函数专门化。他们两人都试图达到相同的目标。我没有为第二个操作符添加专门的版本,因为它没有为问题添加任何新内容。@PhilippMichalski Steven是对的。关键是第二个版本的第二个参数应该是
char*const&
,而不是
MyPtr const&
,因为否则两个签名是相同的,这会导致重新定义错误。@Steven注意到第二个版本中的
strcmp
的所有第二个参数也应该从
rhs.val
更改为
rhs
。无论如何,这两个参数都不能同时使用。所以我编辑了这个问题来反映这一点哦,在所有这些模板在hpp文件中编辑之后,我完全忘记了这一点。真丢脸:-D内联非模板版本现在做这个小动作
template <> bool operator==<char> (MyPtr<char> const& lhs, char* const& rhs)
{ return strcmp(lhs.val,rhs) == 0;}