重载模板类的运算符时的隐式转换 [英] Implicit conversion when overloading operators for template classes

查看:112
本文介绍了重载模板类的运算符时的隐式转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么隐式类型转换不能在类模板上使用外部运算符重载。这是工作的,非模板版本:

I would like to know why implicit type conversion doesn't work with outside operator overloading on class templates. Here is the working, non-templated version:

class foo
{
public:

    foo() = default;

    foo(int that)
    {}

    foo& operator +=(foo rhs)
    {
        return *this;
    }
};

foo operator +(foo lhs, foo rhs)
{
    lhs += rhs;
    return lhs;
}

正如预期,以下行可以正确编译:

As expected, the following lines compile correctly:

foo f, g;
f = f + g; // OK
f += 5; // OK
f = f + 5; // OK
f = 5 + f; // OK

另一方面,当类 foo 被声明为一个简单的模板,如下:

On the other hand, when class foo is declared as a simple template like this:

template< typename T >
class foo
{
public:

    foo() = default;

    foo(int that)
    {}

    foo& operator +=(foo rhs)
    {
        return *this;
    }
};

template< typename T >
foo< T > operator +(foo< T > lhs, foo< T > rhs)
{
    lhs += rhs;
    return lhs;
}

以下行编译时出错:

foo< int > f, g;
f = f + g; // OK
f += 5; // OK
f = f + 5; // Error (no match for operator+)
f = 5 + f; // Error (no match for operator+)



我想了解为什么编译器2)无法使用该类的模板版本的转换构造函数执行隐式类型转换。这是预期的行为吗?除了手动创建所有必要的重载,是否有任何解决方法?

I would like to understand why the compiler (GCC 4.6.2) is unable to perform implicit type conversion using the converting constructor for the template version of the class. Is that the expected behaviour? Apart from manually creating all the necessary overloads, is there any workaround for this?

推荐答案

工作是隐含类型转换(即通过构造函数)不适用于模板参数扣除。
但是,如果你让外部操作符成为一个朋友,那么类型T是已知的,允许编译器调查可以转换的参数以使参数匹配。

The reason it does not just work is that implicit type conversions (that is, via constructors) do not apply during template argument deduction. But it works if you make the outside operator a friend since then the type T is know, allowing the compiler to investigate what can be casted to make the arguments match.

我以Scott Meyers Effective C ++(ed 3)中的Item 46(一个有理数的类)为基础,创建了一个基于你的例子(但删除了C ++ 11的东西)。您的问题几乎是该项目的完全匹配。 Scott还注意到...这种朋友的使用与类的非公开部分的访问无关。

I made an example based on yours (but removed C++11 stuff), inspired by Item 46 (a rational number class) in Scott Meyers Effective C++ (ed 3). Your question is almost an exact match to that item. Scott also notes that ... "this use of friend is not related to the access of non-public parts of the class."

这也允许使用混合的foo< T>,foo< U>等等,只要T和U可以添加等。

This will also allow work with mixes of foo< T >, foo< U > etc as long as T and U can be added etc.

还要看这个帖子: C ++加载过载模糊性

#include <iostream>

using namespace std;

template< class T >
class foo
{
private:
   T _value;
public:
   foo() : _value() {}

   template <class U>
   foo(const foo<U>& that) : _value(that.getval()) {}

   // I'm sure this it can be done without this being public also;
   T getval() const { return _value ; }; 

   foo(const T& that) : _value(that) {}

   friend const foo operator +(foo &lhs,const foo &rhs) 
      {
     foo result(lhs._value+rhs._value); 
     return result;
      };
   friend const foo operator +(foo &lhs,const T &rhsval) 
      {
     foo result(lhs._value+rhsval); 
     return result;
      };
   friend const foo operator +(const T &lhsval,foo &rhs) 
      {
     foo result(lhsval+rhs._value); 
     return result;
      };

   friend foo& operator +=(foo &lhs,const foo &rhs)
      {
     lhs._value+=rhs._value;
     return lhs;
      };   
   friend std::ostream& operator<<(std::ostream& out, const foo& me){
      return out <<me._value;
   }
};

int main(){
   foo< int > f, g;
   foo< double > dd;
   cout <<f<<endl;
   f = f + g;
   cout <<f<<endl;
   f += 3 ;
   cout <<f<<endl;
   f = f + 5;
   cout <<f<<endl;
   f = 7 + f; 
   cout <<f<<endl;      
   dd=dd+f;
   cout <<dd<<endl;      
   dd=f+dd;
   cout <<dd<<endl;      
   dd=dd+7.3;
   cout <<dd<<endl;             
}

这篇关于重载模板类的运算符时的隐式转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆