1

--Quick Before

So before anyone says this question has been answered on another post it hasn't... It was a homework question in the other post and the original question was never answered only told they were wrong.

--Question

I am trying to overload the >> operator to be able to pass in n-number of variables seperated by commas into an object like so...

Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);

I am trying to reuse their usage of the comma seperated argument list but I can't seem to get it to work.

When I overload the << operator like so

void operator<< (const double& is)
{
    std::cout << "hiya " << is << std::endl;
}

and attempt to use it like so

mat << 1.0, 2.0;

only the first value is passed to the operator... The second value is never 'used' as I believe that << has a higher presidence than ,

So my question is what are they doing in libraries like eigen and openCV to be able to have this functionality. I have looked through their code to attempt to understand it but it appears to require a deeper understanding of how C++ works that I don't have and I was hoping someone here could shed some light on it.

Thanks in advance for any advice.

Hewiiitt
  • 306
  • 1
  • 12
  • 1
    Can you use an initializer list? (ie can we put all the numbers inside `{}` braces) `object << { 1,2,3,4,5,6,7,8};` – Martin York Oct 18 '18 at 00:28
  • @MartinYork As nice as this would have been it appears that it is not possible as explained here. https://stackoverflow.com/questions/11420448/initializer-lists-and-rhs-of-operators – Hewiiitt Oct 18 '18 at 02:07

2 Answers2

4

You'll have to overload the insertion operator (<<) and the comma operator (,) such that

mat << 1.0, 2.0;

is translated as:

mat.operator<<(1.0).operator,(2.0);

or

operator,(operator<<(mat, 1.0), 2.0);

Here's a demonstrative program that illustrates the idea without doing anything useful.

struct Foo
{
};

Foo& operator<<(Foo& f, double)
{
  std::cout << "In operator<<(Foo& f, double)\n";
   return f;
}

Foo& operator,(Foo& f, double)
{
   std::cout << "In operator,(Foo& f, double)\n";
   return f;
}

int main()
{
   Foo f;
   f << 10, 20, 30;
}

and its output

In operator<<(Foo& f, double)
In operator,(Foo& f, double)
In operator,(Foo& f, double)
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

You would have to create a temporary from the first argument and surround the entire comma list in parenthesis:

myObj >> (some_temporary(3), 1, ...);

which would require that some_temporary be either a type or helper-function-returning-object that overloads the comma operator and your >> would need to be able to take that type. Otherwise the precedence of >> would "win" and therefore be evaluated before the comma expression is seen.

An uglier alternative would be to have your >> return a type that overloads operator ,() but I believe the first is preferable (actually, I would say this entire scheme is un-preferable).

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
  • So I feel like this is along the right lines... However it looks like the guys over at eigen have found a work around that does the "Some_Temporary" in the background and I don't fully understand how. – Hewiiitt Oct 17 '18 at 22:39
  • The result inside the braces `()` is simply the result of the comma operator. The last element is returned as the result of the expression. – Martin York Oct 18 '18 at 00:32