C++ 类模板上的运算符重载
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4014294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Operator overloading on class templates
提问by Pieter
I'm having some problems defining some operator overloads for template classes. Let's take this hypothetical class for example.
我在为模板类定义一些运算符重载时遇到了一些问题。让我们以这个假设的类为例。
template <class T>
class MyClass {
// ...
};
operator+=
// 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; }
Results in this compiler error:
no match for 'operator+=' in 'classObj2 += classObj1'
operator<<
// 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; }
Results in this compiler warning:
friend declaration 'std::ostream& operator<<(std::ostream&, const MyClass<T>&)' declares a non-template function
运算符+=
// 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'
运算符<<
// 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
What am I doing wrong here?
我在这里做错了什么?
采纳答案by Puppy
// 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;
}
This is invalid for templates. The full source code of the operator must be in all translation units that it is used in. This typically means that the code is inline in the header.
这对模板无效。运算符的完整源代码必须在使用它的所有翻译单元中。这通常意味着代码内联在标头中。
Edit: Technically, according to the Standard, it is possible to export templates, however very few compilers support it. In addition, you CAN also do the above if the template is explicitly instantiated in MyClass.cpp for all types that are T- but in reality, that normally defies the point of a template.
编辑:从技术上讲,根据标准,可以导出模板,但是很少有编译器支持它。此外,如果模板在 MyClass.cpp 中为所有 T- 类型显式实例化,您也可以执行上述操作,但实际上,这通常无视模板的要点。
More edit: I read through your code, and it needs some work, for example overloading operator[]. In addition, typically, I would make the dimensions part of the template parameters, allowing for the failure of + or += to be caught at compile-time, and allowing the type to be meaningfully stack allocated. Your exception class also needs to derive from std::exception. However, none of those involve compile-time errors, they're just not great code.
更多编辑:我通读了你的代码,它需要一些工作,例如重载运算符 []。此外,通常,我会将维度作为模板参数的一部分,允许在编译时捕获 + 或 += 的失败,并允许有意义地堆栈分配类型。您的异常类还需要从 std::exception 派生。然而,这些都不涉及编译时错误,它们只是不是很好的代码。
回答by Johannes Schaub - litb
You need to say the following (since you befriend a whole templateinstead of just a specialization of it, in which case you would just need to add a <>
after the operator<<
):
你需要下面要说的(因为你善待整个模板,而不是只是它的专业化,在这种情况下,你只需要一个补充<>
后operator<<
):
template<typename T>
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);
Actually, there is no need to declare it as a friend unless it accesses private or protected members. Since you just get a warning, it appears your declaration of friendship is not a good idea. If you just want to declare a single specializationof it as a friend, you can do that like shown below, with a forward declaration of the template before your class, so that operator<<
is regognized as a template.
实际上,除非访问私有成员或受保护成员,否则无需将其声明为友元。既然你刚刚收到警告,看来你的友谊宣言不是一个好主意。如果您只想将它的单个特化声明为友元,您可以按照如下所示执行此操作,在您的类之前使用模板的前向声明,以便将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);
Both the above and this way declare specializations of it as friends, but the first declares allspecializations as friends, while the second only declares the specialization of operator<<
as a friend whose T
is equal to the T
of the class granting friendship.
以上和这种方式都将其特化声明为朋友,但第一个声明所有特化为朋友,而第二个声明的特化为operator<<
朋友,其T
等于T
授予友谊的类。
And in the other case, your declaration looks OK, but note that you cannot +=
a MyClass<T>
to a MyClass<U>
when T
and U
are different type with that declaration (unless you have an implicit conversion between those types). You can make your +=
a member template
在另一种情况下,您的声明看起来不错,但请注意,您不能+=
aMyClass<T>
到MyClass<U>
whenT
并且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;
}
回答by user487478
This helped mewith the exact same problem.
这帮助我解决了完全相同的问题。
Solution:
解决方案:
Forward declare the
friend
function before the definition of theclass
itself. For example:template<typename T> class MyClass; // pre-declare the template class itself template<typename T> std::ostream& operator<< (std::ostream& o, const MyClass <T>& x);
Declare your friend function in your class with "<>" appended to the function name.
friend std::ostream& operator<< <> (std::ostream& o, const Foo<T>& x);
friend
在定义class
自身之前向前声明函数。例如:template<typename T> class MyClass; // pre-declare the template class itself template<typename T> std::ostream& operator<< (std::ostream& o, const MyClass <T>& x);
在您的类中声明您的朋友函数,并在函数名称后附加“<>”。
friend std::ostream& operator<< <> (std::ostream& o, const Foo<T>& x);
回答by wilhelmtell
回答by nulleight
This way works:
这种方式有效:
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); }
};