問題描述
我想知道為什么隱式類型轉換不適用于類模板上的外部運算符重載.這是工作的非模板版本:
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+)
我想了解為什么編譯器 (GCC 4.6.2) 無法使用類模板版本的轉換構造函數執(zhí)行隱式類型轉換.這是預期的行為嗎?除了手動創(chuàng)建所有必要的重載之外,是否有任何解決方法?
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.
我根據您的示例(但刪除了 C++11 內容)制作了一個示例,其靈感來自 Scott Meyers Effective C++(第 3 版)中的第 46 項(有理數類).您的問題幾乎與該項目完全匹配.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 等等,只要可以添加 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;
}
這篇關于為模板類重載運算符時的隱式轉換的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!