【问题标题】:Conversion Issues relating to templates (c++)与模板有关的转换问题 (c++)
【发布时间】:2020-01-28 22:17:47
【问题描述】:

我正在尝试编写模板数组类并重载一些运算符。我的部分代码如下:

模板.h:


ma​​in.cpp:


C2679 二进制“”类型右侧操作数的运算符(或没有可接受的转换)

是什么导致了这个错误?

【问题讨论】:

  • 你用来测试的 T 是什么?
  • int findBigPos(Array<T>* arr, int size, int index) 应该是int findBigPos(const Array<T>& arr, int size, int index)

标签: c++ arrays templates


【解决方案1】:

是什么导致了这个错误?

你正在使用

return this < a;

this 是一个指针,而a 是一个对象的引用。将int*int 进行比较是相似的。

int a = 10;
int b = 11;
int* p = &b;
if ( p < a ) { ... } 

这是不对的。

该功能需要以不同的方式实现。您需要比较数组的每一项并返回适当的值。

template<typename T>
bool Array<T>::operator<(const T& a)
{
   int lowerLength = std::min(this->arrLength, a.arrLengh);
   for ( int i = 0; i < lowerLength; ++i )
   {
      if ( this->myArray[i] != a.myArray[i] )
      {
         return (this->myArray[i] < a.myArray[i]);
      }
   }

   // If we get here, return a value based on which array has more elements.
   return (this->arrLength < a.arrLengh)
}

同时,将成员函数设为const 成员函数。

bool Array<T>::operator<(const T& a) const;

并相应地更改实现。

【讨论】:

  • @Anonymous 那是因为您得到的错误与operator&lt; 无关。这只是您的代码存在的众多错误之一。
【解决方案2】:

findBigPos()(以及Driver.cpp 中的其他函数)中,您应该通过引用而不是指针传递arr。当arr 是一个指针时,arr[index]*(arr + index) 相同——它执行指针运算以在给定的偏移量处取消引用指针,它根本不会索引到您的数组中。这就是为什么编译器认为你在​​比较 Array&lt;int&gt; 对象,而不是调用你的 operator[]

试试这个:

#include "wallet.h"
#include "currency.h"
#include "array.h"
#include <iostream>
#include <string>

using namespace std;

template<typename T>
void recurSelectionSort(Array<T>&, int size, int index);

template<typename T>
int findBigPos(Array<T>&, int size, int index);

int main() {

    //code
}

template<typename T>
void recurSelectionSort(Array<T>& arr, int size, int index) // move the biggest element in arr to index
{
    if (index == size) {
        return;
    }
    else if (index < size) {
        int bigPos = findBigPos(arr, size, index); //position of "biggest" element
        T bigVal = arr[bigPos]; //the value of "biggest" element
        T copy = arr[index]; //copy of wat ever is going to get copy

        arr[index] = bigVal;
        arr[bigPos] = copy;
        recurSelectionSort(arr, size, index + 1);
        cout << arr;
    }
}

template<typename T>
int findBigPos(Array<T>& arr, int size, int index)
{
    if (index == size - 1) {
        return index;
    }
    else
    {
        int bigPos = findBigPos(arr, size, index + 1);
        return arr[bigPos] < arr[index] ? index : bigPos;
    }
}

也就是说,您的 Array 类本身也存在一些问题。

  • 您没有实现Rule of 3/5/0。您的类缺少复制构造函数和复制赋值运算符,在 C++11 及更高版本中缺少移动构造函数和移动赋值运算符。

  • 您没有operator[]const 版本供operator&lt;&lt; 使用,因为它需要对const Array&lt;T&gt; 的引用作为输入。

  • 您的 operator[] 未检查 index &lt; 0。最好throwstd::out_of_range 异常而不是int。如果它完全抛出。通常,数组的operator[] 根本不应该执行边界检查。这就是为什么像std::vectorstd::string 这样的容器有一个单独的at() 方法来处理边界检查。

  • 您的operator&lt; 根本没有正确实现。您无法将 Array&lt;T&gt;* 指针与 const T&amp; 引用进行比较。您可能打算在将 this 指针与 a 进行比较之前取消引用它,但这会导致无限递归循环。您应该做的是将const T&amp; a 更改为const Array&lt;T&gt; &amp;a,然后将thiscontentsacontents 进行比较。

试试这个:

#ifndef ARRAY_HEADER
#define ARRAY_HEADER

#include <iostream>
#include <stdexcept>
#include <utility>

template<typename T>
class Array
{
private:
    int arrLength;
    T* myArray;

public:
    Array(int length = 5);
    Array(const Array &a);
    Array(Array &&a);

    virtual ~Array();

    int getLength() const;

    Array& operator=(Array a);

    T& operator[](int index);
    const T& operator[](int index) const;

    bool operator<(const Array &a) const;

    friend std::ostream& operator<<(std::ostream &output, const Array &arr)
    {
        int arrSize = arr.getLength();
        for (int i = 0; i < arrSize; i++) {
            output << arr[i] << " ";
        }
        return output;
    }
};

template<typename T>
Array<T>::Array(int length)
{
    myArray = new T[length];
    arrLength = length;
}

template<typename T>
Array<T>::Array(const Array<T> &a)
{
    myArray = new T[a.arrLength];
    arrLength = a.arrLength;
    for(int i = 0; i < arrLength; ++i)
        myArray[i] = a.myArray[i];
}

template<typename T>
Array<T>::Array(Array<T> &&a)
{
    arrLength = a.arrLength;
    myArray = a.myArray;
    a.myArray = nullptr;
    a.arrLength = 0;
}

template<typename T>
Array<T>::~Array()
{
    delete[] myArray;
}

template<typename T>
int Array<T>::getLength() const
{
    return arrLength;
}

template<typename T>
Array<T>& Array<T>::operator=(Array<T> a)
{
    using std::swap;
    swap(myArray, a.myArray);
    swap(arrLength, a.arrLength);
    return *this;
}

template<typename T>
T& Array<T>::operator[](int index) {
    if ((index < 0) || (index >= arrLength)) {
        throw std::out_of_range("index is out of range");
    }
    return myArray[index];
}

template<typename T>
const T& Array<T>::operator[](int index) const {
    if ((index < 0) || (index >= arrLength)) {
        throw std::out_of_range("index is out of range");
    }
    return myArray[index];
}

template<typename T>
bool Array<T>::operator<(const Array<T> &a) const
{
    if (arrLength < a.arrLength)
        return true;

    if (arrLength == a.arrLength)
    {
        for (int i = 0; i < arrLength; ++i)
        {
            if (myArray[i] != a.myArray[i])
                return myArray[i] < a.myArray[i];
        }
    }

    return false;
}

#endif

【讨论】:

  • @Anonymous 在 StackOverflow 上有很多关于为模板类编写 friend 运算符的问题。例如,C++ template friend operator overloading。在这种情况下,最简单的解决方案是将operator&lt;&lt; 的实现移到其声明中。我已经更新了我的答案以表明这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多