模板类上的二元运算符重载

发布于 2024-07-23 13:03:00 字数 1719 浏览 7 评论 0原文

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

I was recently trying to gauge my operator overloading/template abilities and as a small test, created the Container class below. While this code compiles fine and works correctly under MSVC 2008 (displays 11), both MinGW/GCC and Comeau choke on the operator+ overload. As I trust them more than MSVC, I'm trying to figure out what I'm doing wrong.

Here is the code:

#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;
}

This is the error Comeau gives:

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".

I'm having a hard time trying to get Comeau/MingGW to play ball, so that's where I turn to you guys. It's been a long time since my brain has melted this much under the weight of C++ syntax, so I feel a little embarrassed ;).

EDIT: Eliminated an (irrelevant) lvalue error listed in initial Comeau dump.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

笑,眼淚并存 2024-07-30 13:03:00

我找到了解决方案,感谢 此论坛发帖。 本质上,您需要有一个函数原型,然后才能在类中使用“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;
}

I found the solution thanks to this forum posting. Essentially, you need to have a function prototype before you can use 'friend' on it within the class, however you also need the class to be declared in order to properly define the function prototype. Therefore, the solution is to have two prototype definitons (of the function and the class) at the top. The following code compiles under all three compilers:

#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;
}
恏ㄋ傷疤忘ㄋ疼 2024-07-30 13:03:00
template <typename T>
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs)

这里的“<>” 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);
      ...
};
template <typename T>
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs)

Here the "<>" after operator+ should be removed since you're just declaring a new template, not specializing a general one. Also at least g++ wants to see the template declaration before the friend declaration, so it needs to be moved before the declaration of Container. So the following order of the declarations works:

// 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);
      ...
};
话少情深 2024-07-30 13:03:00

我在 GCC 下进行了尝试,并通过一些更改使其编译和运行。 为了让 GCC 满意,我必须做出两项改变。

一是友元模板函数的声明。 它有自己的模板声明,与类之一分开,因此我在那里使用 U 而不是 Container 类' T 。 我还摆脱了 <> 在运算符+之后。 我认为除非您正在编写模板专业化,否则您不需要这些。

      template<typename U>
      friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);

第二,该行在

Container<int>& c = a + b;

GCC 中不起作用,因为您要求存储对临时对象(加法的结果)的引用。 我删除了&符号,以便有地方存储结果。

我刚才看到你的帖子,由于前向声明,这也有效。 我想我无论如何都会发布这个作为不需要它们的替代方案。 当然我只在GCC中测试过......

I gave this a shot under GCC and got it to compile and run with a few changes. There were two changes I had to make to get GCC happy.

One was the declaration of the friend template function. It is its own template declaration separate from the class one, so I used U instead of the Container class' T there. I also got rid of the <> after the operator+. I don't think you'd need those unless you're writing a template specialization.

      template<typename U>
      friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs);

Two, the line

Container<int>& c = a + b;

didn't fly with GCC because you're asking to store a reference to a temporary (the result of the addition). I removed the ampersand so that there is a place to store the result.

I saw your post just now, that also works because of the forward declarations. I guess I'll post this anyway as an alternative that doesn't require them. Of course I only tested in GCC...

鸠魁 2024-07-30 13:03:00

您最好直接在类中定义该函数。 另外,您应该将参数作为 const 引用传递。

template <typename T>
class Container
{
public:
    friend Container operator+ (Container const & lhs, Container const & rhs)
    {
        // ...
    }
};

You'd be better off defining the function directly in the class. Also, you should pass the parameters as const references.

template <typename T>
class Container
{
public:
    friend Container operator+ (Container const & lhs, Container const & rhs)
    {
        // ...
    }
};
め可乐爱微笑 2024-07-30 13:03:00

“operator+”不是成员函数,也不是模板化的。 只是运算符+采用模板化参数。

 template <typename T>
 Container<T> operator+ (Container<T>& lhs, Container<T>& rhs)

'operator+' is not a member function, and it's not templated. It's just the operator+ which takes templated parameters.'

 template <typename T>
 Container<T> operator+ (Container<T>& lhs, Container<T>& rhs)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文