二进制运算符在模板类上重载

时间:2009-06-07 19:19:14

标签: c++ templates operators operator-overloading

我最近试图测量我的运算符重载/模板能力,作为一个小测试,创建了下面的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转储中列出的(无关)左值错误。

5 个答案:

答案 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)