Overloading Binary Stream Insertaion and Extraction Operators for 2D Arrays yields no operator ">>" matches these operands

Viewed 33

I am trying to solve a question from the Deitel's book. I am asked to implement a program so that it overloads paranthesis operator and this allows user to create 2D array, e.g. chessBoard( row, column ). I am implementing below so far, and the problem is std::cin << arr2; statement yields no operator ">>" matches these operands. What's the problem and how to solve this issue?

array.cpp

#include <iostream>
#include <iomanip>
#include <stdexcept>

#include "array.h"

array::array ( size_t row, size_t col ) 
    : row( row > 0 ? row : throw std::invalid_argument( "Row must be > 0" ) ),
      col( col > 0 ? col : throw std::invalid_argument( "Column must be > 0" ) )
{
    ptr = new double*[row];
    for (size_t i = 0; i < row; i++)
    {
        ptr[i] = new double[col];
        for (size_t j = 0; j < col; j++)
        {
            ptr[i][j] = 0.0;
        }
    }
    size = row * col;
}

array::array( const array &arr ) 
    : row( arr.row ),
      col( arr.col),
      ptr ( new double* [row] )
{
    for (size_t i = 0; i < row; i++)
    {
        for (size_t j = 0; j < col; j++)
        {
            ptr[i][j] = arr.ptr[i][j]; // what to do to use ptr(i,j) here?
        }
        
    }
    
}

array::array(std::initializer_list<std::initializer_list<double>> list)
    :row(list.size())
{
    ptr = new double*[row];
    std::initializer_list < std::initializer_list <double>> ::iterator roww;
    std::initializer_list<double>::iterator coll;
    size_t i, j;
    
    for (roww = list.begin(), i = 0; roww != list.end(); ++i, roww++)
    {
        col = roww->size();
        ptr[i] = new double[col];
        for (coll = roww->begin(), j = 0; coll < roww->end(); ++j, coll++)
        {
            ptr[i][j] = *coll; // // what to do to use ptr(i,j) here?
        }   
    }
}

array::~array() {
    delete []*ptr;
}

double array::operator()( size_t row, size_t col ) {

    if ( row < 0 && col < 0 ) {
        throw std::invalid_argument( "Dimensions must be positive " );
    } 
    return ptr[row][col]; // // what to do to use ptr(row,col) here?
}

std::ostream &operator<<(std::ostream &output, const array &&arr) {
    for (size_t i = 0; i < arr.row; i++)
    {
        for (size_t j = 0; j < arr.col; j++)
        {
            output << arr.ptr[i][j];
        }
        output << std::endl;
    }
    return output;
}

std::istream &operator>>( std::istream &input, array &&a ) {
    //output private ptr-based array
    for (size_t i = 0; i < a.row; i++)
    {
        for (size_t j = 0; j < a.col; j++)
        {
            input >> a.ptr[i][j];
        }
    }
    return input;
}

size_t array::getSize() const {
    return row * col;
}

size_t array::getRow() const {
    return row;
}

size_t array::getColumn() const {
    return col;
}

main.cpp

#include <iostream>
#include <stdexcept>
#include "array.h"

int main(int argc, char const *argv[])
{
    array arr2(2,3);
    std::cin >> arr2; // yields error
    
    array arr2{{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}};
    

    std::cout << arr2; // yields error
    
    return 0;
}

Additionally, as I stated with comments , I wanna use my overloaded paranthesis operator () to reach the specific index of my array inside function of array.cpp. But if I do this, it yields expression preceding parentheses of apparent call must have (pointer-to-) function type error. How to fix it? Thx for your helps.

1 Answers

I fixed the issues by taking consider the suggestions in the comment into account.

The first problem is inside the first constructor. It doesn't allocate the memory appropriately. To fix it:

array::array ( size_t row, size_t col ) 
    : row( row > 0 ? row : throw std::invalid_argument( "Row must be > 0" ) ),
      col( col > 0 ? col : throw std::invalid_argument( "Column must be > 0" ) )
{
    ptr = new double*[row];
    for (size_t i = 0; i < row; i++)
    {
        ptr[i] = new double[col];
        for (size_t j = 0; j < col; j++)
        {
            ptr[i][j] = 0.0;
        }
    }
}

The second problem is that the deallocating the memory. The idea behind it is actually the same as the allocation.

array::~array() {
    for (size_t i = 0; i < row; i++)
    {
        delete []ptr[i]; // delete arrays
    }
    delete []ptr; // delete pointer array
}

Lastly, I found a solution for binary stream insertion/extraction operators. Actually, the variable arr, whose datatype is array which is user-defined class is not a 2D array, but the pointer variable called ptr, a private member of class array, is 2D array, so we need to define ptr as 2D, not arr. To that end, we need to regulate our function definitions as below: Use the prototypes in your .h file as private member:

friend std::istream &operator>>( std::istream &, array &);
friend std::ostream &operator<<( std::ostream &, const array & );

Then complete the bodies in your .cpp file as:

std::ostream &operator<<(std::ostream &output, const array &arr) {
    for (size_t i = 0; i < arr.row; i++)
    {
        for (size_t j = 0; j < arr.col; j++)
        {
            std::cout << std::setw(2 * arr.col + 1) << arr.ptr[i][j];
        }
        output << std::endl;   
    }
    return output;
}

std::istream &operator>>( std::istream &input, array &a ) {
    //output private ptr-based array
    for (size_t i = 0; i < a.row; i++)
    {
        for (size_t j = 0; j < a.col; j++)
        {
            input >> a.ptr[i][j];
        }
    }
    return input;
}
Related