Pie*_*ter 14 c++ templates operator-overloading
我在为模板类定义一些运算符重载时遇到了一些问题.让我们以这个假设的类为例.
template <class T>
class MyClass {
// ...
};
Run Code Online (Sandbox Code Playgroud)
操作者+ =
// In MyClass.h
MyClass<T>& operator+=(const MyClass<T>& classObj);
// In MyClass.cpp
template <class T>
MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) {
// ...
return *this;
}
Run Code Online (Sandbox Code Playgroud)
导致此编译器错误:
no match for 'operator+=' in 'classObj2 += classObj1'
Run Code Online (Sandbox Code Playgroud)运营商<<
// In MyClass.h
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);
// In MyClass.cpp
template <class T>
std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj) {
// ...
return out;
}
Run Code Online (Sandbox Code Playgroud)
结果在此编译器警告:
friend declaration 'std::ostream& operator<<(std::ostream&, const MyClass<T>&)' declares a non-template function
Run Code Online (Sandbox Code Playgroud)我在这做错了什么?
Joh*_*itb 13
你需要下面要说的(因为你善待整个模板,而不是只是它的专业化,在这种情况下,你只需要添加一个<>后operator<<):
template<typename T>
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);
Run Code Online (Sandbox Code Playgroud)
实际上,除非访问私人或受保护的成员,否则无需将其声明为朋友.既然你刚收到警告,那么你的友情宣言似乎不是一个好主意.如果你只是想将它作为朋友声明一个特殊化,你可以像下面所示那样做,在你的类之前使用模板的前向声明,这样就可以operator<<被认为是模板.
// before class definition ...
template <class T>
class MyClass;
// note that this "T" is unrelated to the T of MyClass !
template<typename T>
std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);
// in class definition ...
friend std::ostream& operator<< <>(std::ostream& out, const MyClass<T>& classObj);
Run Code Online (Sandbox Code Playgroud)
以上和这种方式都将它的特化声明为朋友,但第一个声明所有特化作为朋友,而第二个仅宣称operator<<作为朋友的专业化,其T等于T授予友谊的类的专业.
而在另一种情况下,你的声明看起来不错,但要注意,你不能+=一个MyClass<T>一个MyClass<U>的时候T和U不同的类型与声明(除非你有这些类型之间的隐式转换).您可以成为+=会员模板
// In MyClass.h
template<typename U>
MyClass<T>& operator+=(const MyClass<U>& classObj);
// In MyClass.cpp
template <class T> template<typename U>
MyClass<T>& MyClass<T>::operator+=(const MyClass<U>& classObj) {
// ...
return *this;
}
Run Code Online (Sandbox Code Playgroud)
Pup*_*ppy 10
// In MyClass.h
MyClass<T>& operator+=(const MyClass<T>& classObj);
// In MyClass.cpp
template <class T>
MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) {
// ...
return *this;
}
Run Code Online (Sandbox Code Playgroud)
这对模板无效.运算符的完整源代码必须位于其使用的所有转换单元中.这通常意味着代码在标题中内联.
编辑:从技术上讲,根据标准,可以导出模板,但很少有编译器支持它.此外,如果模板在MyClass.cpp中为所有类型的T-显式实例化,您也可以执行上述操作,但实际上,这通常会违反模板的要点.
更多编辑:我读了你的代码,它需要一些工作,例如重载operator [].另外,通常,我会将维度作为模板参数的一部分,允许在编译时捕获+或+ =的失败,并允许类型有意义地堆栈分配.您的异常类还需要从std :: exception派生.但是,这些都不涉及编译时错误,它们只是不是很好的代码.
http://www.parashift.com/c++-faq-lite/template-friends.html
这帮助我解决了完全相同的问题。
索恩:
在定义类本身之前,先声明Friend函数。例如:
template<typename T> class MyClass; // pre-declare the template class itself
template<typename T> std::ostream& operator<< (std::ostream& o, const MyClass <T>& x);
Run Code Online (Sandbox Code Playgroud)在类中声明您的朋友函数,并在函数名称后附加“ <>”。
friend std::ostream& operator<< <> (std::ostream& o, const Foo<T>& x);
Run Code Online (Sandbox Code Playgroud)