[英]Inheriting from a templated class with operator overloading. ambiguous overload for 'operator*'
出于学习目的,我正在尝试使用模板化类和继承。 其中一件事情是,我希望我的类能够使用+=
, +
, -=
, -
, *
, *=
等运算符。为此,我开发了一个类,该类基本上是数据:
template<typename T, int N>
class Array
{
public:
// Constructor
Array( T value = T(0))
{
/* Initialize the array with the same value everywhere */
}
template<typename M>
Array(const Array<M,N>& other)
{
/* Copy constructor allowing for type change */
}
// Destructor
~Array()
{
/* no need to call any destructor since it is a smart pointer */
}
// Product
template<typename M>
Array<T,N>& operator*=(const M& rhs)
{
/* implementation */
}
template<typename M>
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
{
/* implementation */
}
template<typename M>
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
{
/* implementation */
}
Array<T,N>& operator*=(const Array<T,N>& rhs)
{
/* implementation */
}
friend Array<T,N> operator*(const Array<T,N>& lhs,const Array<T,N>& rhs)
{
/* implementation */
}
// String
std::string str() const
{
/* return a string containing the array */
}
private:
std::shared_ptr<T> data_;
size_t n_;
};
我已经使用以下代码测试了此类,没有任何问题:
// Test friend Array<T,N> operator*(const Array<T,N>& lhs,const Array<T,N>& rhs)
Array<double,2> array1(1);
std::cout<<"array1: "<<array1.str()<<std::endl;
Array<double,2> array2(2);
std::cout<<"array2: "<<array2.str()<<std::endl;
Array<int,2> array3 = array1*array2;
std::cout<<"array3: array1*array2"<<array3.str()<<std::endl;
// Test friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
Array<double,2> array4 = 2*array1;
std::cout<<"array4: 2*array1"<<array4.str()<<std::endl;
// Test friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
Array<double,2> array5 = array1*5;
std::cout<<"array5: array1*3"<<array5.str()<<std::endl;
然后,我从该数组继承以创建具有特定成员函数的大小为3的数组
template<typename T>
class Vector3: public Array<T,3>
{
public:
// Use Array constructors
using Array<T,3>::Array;
// Specific function
template<typename M>
Vector3 crossProduct(const Vector3& other)
{
/* implementation */
}
};
我想按以下方式使用它(请注意,它与Array<T,N>
之前相同Array<T,N>
但与Vector3<T>
):
// Test friend Array<T,N> operator*(const Array<T,N>& lhs,const Array<T,N>& rhs)
Vector3<double> vector1(1);
std::cout<<"vector1: "<<vector1.str()<<std::endl;
Vector3<double> vector2(2);
std::cout<<"vector2: "<<vector2.str()<<std::endl;
Vector3<int> vector3 = vector1*vector2;
std::cout<<"vector3: vector1*vector2"<<vector3.str()<<std::endl;
// Test friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
Vector3<double> vector4 = 2*vector1;
std::cout<<"vector4: 2*vector1"<<vector4.str()<<std::endl;
// Test friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
Vector3<double> vector5 = vector1*5;
std::cout<<"vector5: vector1*3"<<vector5.str()<<std::endl;
编译时,出现以下错误:
error: ambiguous overload for 'operator*' (operand types are 'Vector3<double>' and 'Vector3<double>')
Vector3<int> vector3 = vector1*vector2;
^
note: candidates are:
note: Array<T, N> operator*(M, const Array<T, N>&) [with M = Vector3<double>; T = int; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
note: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = Vector3<double>; T = int; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
note: Array<T, N> operator*(M, const Array<T, N>&) [with M = Vector3<double>; T = double; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
note: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = Vector3<double>; T = double; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
note: Array<double, 3> operator*(const Array<double, 3>&, const Array<double, 3>&)
friend Array<T,N> operator*(const Array<T,N>& lhs,const Array<T,N>& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector4 = 2*vector1;
^
note: candidate 1: Array<T, N> operator*(M, const Array<T, N>&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
note: candidate 2: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = Vector3<double>; T = int; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector4 = 2*vector1;
^
note: candidate 1: Array<T, N> operator*(M, const Array<T, N>&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
note: candidate 2: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = Vector3<double>; T = double; int N = 2]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector4 = 2*vector1;
^
note: candidate 1: Array<T, N> operator*(M, const Array<T, N>&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
note: candidate 2: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = Vector3<double>; T = int; int N = 2]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector4 = 2*vector1;
^
note: candidate 1: Array<T, N> operator*(M, const Array<T, N>&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
note: candidate 2: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = Vector3<double>; T = double; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector5 = vector1*5;
^
note: candidate 1: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
note: candidate 2: Array<T, N> operator*(M, const Array<T, N>&) [with M = Vector3<double>; T = int; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector5 = vector1*5;
^
note: candidate 1: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
note: candidate 2: Array<T, N> operator*(M, const Array<T, N>&) [with M = Vector3<double>; T = double; int N = 2]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector5 = vector1*5;
^
note: candidate 1: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
note: candidate 2: Array<T, N> operator*(M, const Array<T, N>&) [with M = Vector3<double>; T = int; int N = 2]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
Vector3<double> vector5 = vector1*5;
^
note: candidate 1: Array<T, N> operator*(const Array<T, N>&, const M&) [with M = int; T = double; int N = 3]
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
^
note: candidate 2: Array<T, N> operator*(M, const Array<T, N>&) [with M = Vector3<double>; T = double; int N = 3]
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
^
我不明白为什么继承类会出现错误,而基类却没有。 我尝试using Array<T,3>::operator*
,但是编译器在此行抱怨说:
error: no members matching 'Array<double, 3>::operator*' in 'class Array<double, 3>'
using Array<T,3>::operator*;
^
谁能解释我为什么在子类中不能正确解析运算符,而在基类中却无法解决? 如果我必须做一些using Array<T,3>::operator...
事情using Array<T,3>::operator...
该怎么写?
谢谢!
之所以会出现这些错误,是因为当编译器尝试匹配运算符参数时,当在基类的实例上调用相同的运算符时,它将强制对基类执行额外的向下强制转换,同时获得完全匹配。 您应该使用::std::enable_if
对M
类型施加其他限制,如下所示:
template
<
typename M
, typename TEnable = typename ::std::enable_if_t
<
::std::is_integral<M>::value
||
::std::is_floating_point<M>::value
>
>
当您将*运算符声明为非成员朋友函数模板时, Array<T,3>
类中没有operator*
。
在VTT提供的提示之后,我能够修复代码。 由于我不使用c ++ 14,因此我设法在没有std::enable_if_t
情况下做到了。 这是最终的运算符:
// Product
template<typename M, typename std::enable_if<!std::is_base_of<Array<T,N>,M>::value>::type>
Array<T,N>& operator*=(const M& rhs)
{
/* implementation */
}
template<typename M, typename std::enable_if<!std::is_base_of<Array<T,N>,M>::value>::type>
friend Array<T,N> operator*(const Array<T,N>& lhs,const M& rhs)
{
/* implementation */
}
template<typename M, typename std::enable_if<!std::is_base_of<Array<T,N>,M>::value>::type>
friend Array<T,N> operator*( M lhs, const Array<T,N>& rhs)
{
/* implementation */
}
Array<T,N>& operator*=(const Array<T,N>& rhs)
{
/* implementation */
}
friend Array<T,N> operator*(const Array<T,N>& lhs,const Array<T,N>& rhs)
{
/* implementation */
}
希望这会对其他人有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.