簡體   English   中英

從帶有操作符重載的模板化類繼承。 “運算符*”的模棱兩可的重載

[英]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_ifM類型施加其他限制,如下所示:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM