0

I am trying to code a template array class and overloading some operators. Part of my code is as follows:

template.h:


main.cpp:


C2679 binary '<': no operator found which takes a right-hand operand of type 'Array<int>' (or there is no acceptable conversion)

What is causing this error?

ChaosNova
  • 11
  • 3

2 Answers2

2

What is causing this error?

You are using

return this < a;

this is a pointer while a is a reference to an object. It's analgous to comparing an int* with an int.

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

That is not right.

That function needs to be implemented differently. You need to compare each item of the arrays and return an appropriate value.

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

While at it, make the member function a const member function.

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

and change the implementation accordingly.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • @Anonymous That is because the error you are getting has nothing to do with `operator<`. That is just one of many errors your code has. – Remy Lebeau Jan 28 '20 at 23:39
0

In findBigPos() (and your other functions in Driver.cpp, too), you should be passing arr by reference, not by pointer. When arr is a pointer, arr[index] is the same as *(arr + index) - it performs pointer arithmetic to dereference the pointer at a given offset, it does not index into your array at all. That is why the compiler thinks you are comparing Array<int> objects, and not calling your operator[].

Try this instead:

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

That said, there are some issues with your Array class itself, too.

  • You are not implementing the Rule of 3/5/0. Your class is lacking a copy constructor and a copy assignment operator, and in C++11 and later a move constructor and a move assignment operator.

  • you don't have a const version of your operator[] for your operator<< to use, since it takes a reference to a const Array<T> as input.

  • your operator[] is not checking for index < 0. And it would be better to throw a std::out_of_range exception instead of an int. If it throws at all. Typically, an array's operator[] should not perform bounds checking at all. That is why containers like std::vector and std::string have a separate at() method for handling bounds checking.

  • your operator< is not implemented correctly at all. You can't compare a Array<T>* pointer to a const T& reference. You probably meant to dereference the this pointer before comparing it to a, but then that would lead to an endless recursive loop. What you should do instead is change const T& a to const Array<T> &a and then compare the contents of this to the contents of a.

Try this:

#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
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • @Anonymous there are numerous questions on StackOverflow related to writing `friend` operators for templated classes. For instance, [C++ template friend operator overloading](https://stackoverflow.com/questions/3989678/). The simplest solution in this case would be to move the implementation of `operator<<` into its declaration. I've updated my answer to show that. – Remy Lebeau Jan 29 '20 at 07:14