0

I have a two dimensional smart pointer array of doubles. I can assign values to it, and display it, but I am having trouble passing it to a function that takes double** as an input. A simple get() does not work.

#include <iostream>
#include <memory>
using namespace std;
# define DIM1 3
# define DIM2 4

void funcCall(double** item)
{
    cout<< "Test function.";
}

int main() {

    std::unique_ptr<std::unique_ptr<double[]>> myArray(new std::unique_ptr<double[]>[DIM1]);

    for (int i = 0; i < DIM1; i++)
    {
        myArray.get()[i].reset(new double[DIM2]);
    }

    std::cout<<"Assign values"<<std::endl;
    for (int i = 0; i < DIM2; i++)
    {
        for (int j = 0; j < DIM1; j++)
        {
            myArray.get()[j][i] = (j+1)*(i+1);
        }
    }

    funcCall(myArray.get());    

    return 0;
}

When I compile this, I get:

error: cannot convert 'std::unique_ptr<std::unique_ptr<double []> >::pointer {aka std::unique_ptr<double []>*}' to 'double**' for argument '1' to 'void funcCall(double**)'  funcCall(myArray.get())
5
  • 2
    You really don't want to nest unique_ptrs in this case. Commented Oct 30, 2015 at 16:44
  • Just add casting to (double**) when calling the function. If the only problem is compilation - it should solve your problem Commented Oct 30, 2015 at 16:44
  • 2
    Do not prefer #define for constants in c++ instead prefer const type name; (e.g., const int DIM1 = 3;). Commented Oct 30, 2015 at 16:45
  • 2
    Use a 1d vector and index calculation x + y * width and wrap this in a 2d array class and use this instead. Commented Oct 30, 2015 at 16:49
  • You will not be avle to do this. It is akin to the fact that int arr[10][15] can not be passed into function as double** Commented Oct 30, 2015 at 17:14

2 Answers 2

1
void funcCall(std::unique_ptr<std::unique_ptr<double[]>> & arr)

Should do what you want, but...

but...

It sounds like you are trying to reinvent the wheel. Don't do that. Unless this is for an assignment or personal education, in that case go nuts.

Instead, use one of the built-in containers.

Because DIM1 and DIM2 are constant, you can use

std::array<std::array<double, DIM2>,DIM1> myArray;

and

void funcCall(std::array<std::array<double, DIM2>,DIM1> arr)

But odds are pretty good you want a dynamic solution. In that case, try

std::vector<std::vector<double>> myArray(DIM1, std::vector<double>(DIM2));

and

void funcCall(std::vector<std::vector<double>> arr)

but...

This is a sucker bet, to be honest. An array of arrays or a vector of vectors are not contiguous in memory so the computer has to hop around in storage, wasting time on unnecessary cache misses and the time spent loading and possibly reloading cache often take longer than the computations involved. All the 133t math in the world can't help you at this point because you've become gated by IO, and IO is sssssssssslllloooowwwwwwww.

What you really want is one nice 1 dimensional array that's indexed manually. with row * number of columns + column. Sure, manual index looks like extra work, but stop and think: How much math is the compiler doing in the background to make you array work, hmmm? Probably about the same. You just don't get to see it.

Let's stuck with std::vector for now, but the same applies to std::array or even a good ol' static array or a dynamic inside a smart pointer.

std::vector<double> myArray(DIM1*DIM2);

Using this is relatively simple:

myArray[row*DIM2 + column];

The function is:

void funcCall(std::vector<double> arr)

But this is easily wrapped in a class and simplified further:

class matrix
{
private: 
    std::vector<double> myArray;
    size_t nrRows;
    size_t nrColumns;

public:
    matrix(size_t rows, size_t columns): 
        myArray(rows*columns), nrRows(rows), nrColumns(columns)
    {

    }

    double& operator()(size_t row, size_t column)
    {
        return myArray[row* nrColumns + column];
    }
    double operator()(size_t row, size_t column) const
    {
        return myArray[row* nrColumns + column];
    }
};

Construction:

matrix mat(DIM1, DIM2);

and usage:

double d = mat(1,2);

or

mat(2,1) = 3.14;
Sign up to request clarification or add additional context in comments.

2 Comments

I think std::array of std::arrays IS contiguous. Isn't it?
static 2d Array will be, or at least it was in C. std::array of std::array should be at least close since the inner arrays are all statically allocated inside the outer array, but I'm not sure this is guaranteed. Standard dynamically allocated 2d array and vector of vector, massively unlikely.
0

The types of the call and the function header don't match. You can't treat a unique_ptr as a regular pointer.

One solution is to change your function definition to:

void funcCall(std::unique_ptr<double[]> *item)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.