我在为模板类定义一些运算符重载时遇到了一些问题。让我们以这个假设的课程为例。
template <class T>
class MyClass {
// ...
};
运算符+ =
// 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;
}
导致此编译器错误:
no match for 'operator+=' in 'classObj2 += classObj1'
运营商LT;&LT;
// 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;
}
此编译器警告的结果:
friend declaration 'std::ostream& operator<<(std::ostream&, const MyClass<T>&)' declares a non-template function
我在这里做错了什么?
答案 0 :(得分:13)
您需要说明以下内容(因为您与整个模板建立了联系,而不仅仅是它的特化),在这种情况下,您只需要在{{{{}}之后添加<>
1}}):
operator<<
实际上,除非访问私人或受保护的成员,否则无需将其声明为朋友。因为你只是得到警告,所以你的友情宣言似乎不是一个好主意。如果您只是想将其作为朋友的单一特化声明,您可以像下面所示那样做,并在课前使用模板的前向声明,以便template<typename T>
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);
被认可作为模板。
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);
的专业化为朋友,{ {1}}等于授予友谊的类的operator<<
。
在另一种情况下,您的声明看起来不错,但请注意,T
和T
时,您+=
MyClass<T>
MyClass<U>
T
具有该声明的不同类型(除非您在这些类型之间进行隐式转换)。您可以将U
设为会员模板
+=
答案 1 :(得分: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;
}
这对模板无效。运算符的完整源代码必须位于其使用的所有转换单元中。这通常意味着代码在标题中内联。
编辑:从技术上讲,根据标准,可以导出模板,但很少有编译器支持它。此外,如果模板在MyClass.cpp中为所有类型的T-显式实例化,你也可以执行上述操作,但实际上,这通常会违反模板的点。
更多编辑:我阅读了您的代码,它需要一些工作,例如重载operator []。另外,通常,我会将维度作为模板参数的一部分,允许在编译时捕获+或+ =的失败,并允许类型有意义地堆栈分配。您的异常类还需要从std :: exception派生。但是,这些都不涉及编译时错误,它们只是不是很好的代码。
答案 2 :(得分:4)
http://www.parashift.com/c++-faq-lite/template-friends.html
这帮助了我完全相同的问题。
Soln:
在类本身的定义之前转发声明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);
使用“&lt;&gt;”在您的班级中声明您的朋友功能附加到函数名称。
friend std::ostream& operator<< <> (std::ostream& o, const Foo<T>& x);
答案 3 :(得分:0)
答案 4 :(得分:-1)
这种方式有效:
class A
{
struct Wrap
{
A& a;
Wrap(A& aa) aa(a) {}
operator int() { return a.value; }
operator std::string() { stringstream ss; ss << a.value; return ss.str(); }
}
Wrap operator*() { return Wrap(*this); }
};