我最近试图测量我的运算符重载/模板能力,作为一个小测试,创建了下面的Container类。虽然此代码编译良好并且在MSVC 2008(显示11)下正常工作,但MinGW / GCC和Comeau都在operator+
重载时阻塞。因为我比MSVC更信任他们,所以我想弄清楚我做错了什么。
以下是代码:
#include <iostream>
using namespace std;
template <typename T>
class Container
{
friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs);
public: void setobj(T ob);
T getobj();
private: T obj;
};
template <typename T>
void Container<T>::setobj(T ob)
{
obj = ob;
}
template <typename T>
T Container<T>::getobj()
{
return obj;
}
template <typename T>
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs)
{
Container<T> temp;
temp.obj = lhs.obj + rhs.obj;
return temp;
}
int main()
{
Container<int> a, b;
a.setobj(5);
b.setobj(6);
Container<int> c = a + b;
cout << c.getobj() << endl;
return 0;
}
这是Comeau给出的错误:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 27: error: an explicit template argument list is not allowed
on this declaration
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs)
^
1 error detected in the compilation of "ComeauTest.c".
我很难让Comeau / MingGW去打球,这就是我转向你们的地方。很长一段时间以来,我的大脑在C ++语法的压力下融化了这么多,所以我觉得有点尴尬;)。
编辑:消除了初始Comeau转储中列出的(无关)左值错误。
答案 0 :(得分:6)
我找到了解决方案,感谢to this forum posting。基本上,你需要有一个函数原型才能在类中使用'friend',但是你还需要声明这个类才能正确定义函数原型。因此,解决方案是在顶部有两个原型定义(功能和类)。以下代码在所有三个编译器下编译:
#include <iostream>
using namespace std;
//added lines below
template<typename T> class Container;
template<typename T> Container<T> operator+ (Container<T>& lhs, Container<T>& rhs);
template <typename T>
class Container
{
friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs);
public: void setobj(T ob);
T getobj();
private: T obj;
};
template <typename T>
void Container<T>::setobj(T ob)
{
obj = ob;
}
template <typename T>
T Container<T>::getobj()
{
return obj;
}
template <typename T>
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs)
{
Container<T> temp;
temp.obj = lhs.obj + rhs.obj;
return temp;
}
int main()
{
Container<int> a, b;
a.setobj(5);
b.setobj(6);
Container<int> c = a + b;
cout << c.getobj() << endl;
return 0;
}
答案 1 :(得分:2)
template <typename T>
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs)
这里的“&lt;&gt;”应该删除operator+
后,因为您只是声明一个新模板,而不是专门的一般模板。此外,至少g++
希望在朋友声明之前看到模板声明,因此需要在声明Container
之前移动它。因此,声明的以下顺序有效:
// forward declaration of Container<T>
template <typename T>
class Container;
template <typename T>
Container<T> operator+(Container<T>& lhs, Container<T>& rhs)
{ ... }
template <typename T>
class Container
{
friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs);
...
};
答案 2 :(得分:1)
我在GCC下给了它一个镜头并让它编译并运行一些更改。为了让GCC满意,我必须做出两个改变。
一个是朋友模板功能的声明。它是自己的模板声明,与第一类分开,因此我使用U而不是Container类'T.我也摆脱了&lt;&gt;经营者+之后。除非你正在编写模板专业化,否则我认为你不需要那些。
template<typename U>
friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);
二,行
Container<int>& c = a + b;
没有与GCC一起飞行,因为您要求存储对临时的引用(添加的结果)。我删除了&符,以便有一个存储结果的地方。
我刚刚看到你的帖子,因为前向声明也有效。我想我会发布这个作为不需要它们的替代方案。当然我只在GCC测试过......
答案 3 :(得分:1)
你最好直接在课堂上定义这个功能。此外,您应该将参数作为const
引用传递。
template <typename T>
class Container
{
public:
friend Container operator+ (Container const & lhs, Container const & rhs)
{
// ...
}
};
答案 4 :(得分:0)
'operator +'不是成员函数,它不是模板化的。它只是运算符+,它采用模板化参数。'
template <typename T>
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs)