gpt4 book ai didi

c++ - 为模板类重载运算符时的隐式转换

转载 作者:IT老高 更新时间:2023-10-28 21:52:18 25 4
gpt4 key购买 nike

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

class foo
{
public:

foo() = default;

foo(int that)
{}

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

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

正如预期的那样,以下行编译正确:

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

另一方面,当类 foo 被声明为这样的简单模板时:

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+)

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

最佳答案

它不正常工作的原因是隐式类型转换(即通过构造函数)在模板参数推导期间不适用。但是如果你让外部运算符成为 friend ,那么它就可以工作,因为类型 T 是已知的,允许编译器调查可以强制转换的内容以使参数匹配。

我根据你的例子做了一个例子(但删除了 C++11 的东西),灵感来自 Scott Meyers Effective C++(ed 3)中的 Item 46(一个有理数类)。您的问题几乎与该项目完全匹配。 Scott 还指出……“这种对 friend 的使用与类的非公共(public)部分的访问无关。”

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

也可以看看这个帖子:C++ addition overload ambiguity

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

关于c++ - 为模板类重载运算符时的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8890051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com