2

I am using OpenCV and I do not like the ouput of:

std::cout << matrix << std::endl; when matrix has type cv::Mat.

Is it possible to redefine the effect of operator << on objects of an existing class without having to modify the code of the class ?

I know that I could write a simple function that would produce a string out of a cv::Mat but the result would be less readable (I think) and I am a beginner in C++ so I may have missed something.

I found this SO question so I tried:

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>

std::ostream& operator<<(std::ostream& os, const cv::Mat& mat)
{
     os << "test";
     return os;
}

int main(int argc, char** argv)
{
    cv::Mat m(2,2, CV_8UC3, cv::Scalar(0,0,255));
    std::cout << m << std::endl;
}

But I got:

main.cpp:14:18: error: ambiguous overload for ‘operator<<’ in ‘std::cout << m’

edit: I do not think it is a duplicate of this question because I do not have access to the code of the library (OpenCV is opensource so I could in theory modify it but that would be a bad idea: harder to maintain, to redistribute my code, etc.).

Gabriel Devillers
  • 3,155
  • 2
  • 30
  • 53
  • If the object already has a non meber function defined you cannot redefine it. – NathanOliver Jun 30 '17 at 13:56
  • Possible duplicate of [How to properly overload the << operator for an ostream?](https://stackoverflow.com/questions/476272/how-to-properly-overload-the-operator-for-an-ostream) – Javia1492 Jun 30 '17 at 13:57
  • @Javia1492 I've added an edit to explain why I think it is not a duplicate – Gabriel Devillers Jun 30 '17 at 14:04
  • This cannot be done, you can create a function though, that does the same thing, but once it is defined it cannot be redefined. – api55 Jul 03 '17 at 11:10

2 Answers2

3

You cannot replace an overload by another one. If the output operator has suitable hooks to change how the output is change there may be a chance to modify the output this way. Whether this particular output operator has such a hook I don't know.

The reasonably readable work-around is to create a simple wrapper:

struct MatFormatter {
    cv::Mat const& mat;
};
std::ostream& operator<< (std::ostream& out, MatFormatter const& formatter) {
    // format formatter.mat to your liking
}
MatFormatter format(cv::Mat const& mat) {
    return MatFormatter{mat};
}
// ...
out << format(mat) << '\n';
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

cv::Mat already has a user-defined operator<< overload, you can't add another one yourself, you'd have to change the overload or add some kind of function that does what you want it to do, as long as it isn't an operator that already has been defined for that class.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122