3

I would like to write a function in C++ that takes a matrix as an optional argument. If the user ends up passing the matrix when calling the function, it will be modified by the function, so I'm implementing a pass by reference.

According to the accepted answer for this previous question, this can be done by making the default value an empty Mat, such as:

void foo(..., cv::Mat &matrix = cv::Mat()) {
    // code

    return;
}

However, when I try to compile this in OpenCV 3.2, I get the «invalid initialization of non-const reference of type ‘cv::Mat&’ from an rvalue of type ‘cv::Mat’» error.

Has this feature changed since OpenCV 2.4, or could the issue be somewhere else?

hfs
  • 31
  • 2
  • 1
    Unfortunately you managed to use the one part of that question which is wrong, contradicting what is said in the first sentence. – Dan Mašek Jun 28 '17 at 13:09
  • 1
    Indeed, the accepted answer on that link is partially wrong. Maybe we should resolve that one and then mark this one as a duplicate? – E_net4 Jun 28 '17 at 13:11
  • I did not specify in my original post, but my problem stems from trying to import someone else's code (from github) where this implementation is used in several functions. This, combined with the thread I cited, led me to believe there was probably an element to make it work that I'm somehow missing. Perhaps I place too much faith in people, but why would they upload the source code consisting of more than 4000 lines and not even bother to check if it works first? – hfs Jun 28 '17 at 14:38

2 Answers2

8

I might be wrong because I'm a beginner in those matters but here's what I think. You want to pass by ref an optional argument. The issue is that a reference with the symbol & is a reference to an l-value, which is an object that exists. C++ does not allow what you have written because matrix is an r-value, that is a temporary object that has not an actual memory address associated to it. The only way you can pass cv::Mat &matrix = cv::Mat() is by const-ing it,const cv::Mat &matrix = cv::Mat() which of course is not what you need.

The simplest solution IMHO is to just overload your function definition so that you have

void foo(...args); void foo(...args, cv::Mat &matrix);

Hope it helps

  • 2
    Yep, that's the way to do it. Consider providing the implementation as well. Should be something like this: `{ cv::Mat dummy; foo(..., dummy); }`. Also format your code with 4-space indentation. – E_net4 Jun 28 '17 at 13:26
4

This is because C++ does not allow you to initialize a non-const reference with an rvalue.

So you can either:

1) make the reference const -- wouldn't suit you since you want to change the content of matrix in the function

or

2) have a cv::Mat init variable stored globally in your module:

static const cv::Mat g_mat = cv::Mat();

void foo(..., cv::Mat &matrix = g_mat) {