How can comma-separated initialization be implemented, for example, in Eigen, in C ++?

Here is part of the Eigen documentation:

Matrix3f m; m << 1, 2, 3, 4, 5, 6, 7, 8, 9; std::cout << m; 

Output:

 1 2 3 4 5 6 7 8 9 

I could not understand how all values โ€‹โ€‹separated by commas would be captured by the operator <<above. I did a little experiment:

 cout << "Just commas: "; cout << 1, 2, 3, 4, 5; cout << endl; cout << "Commas in parentheses: "; cout << ( 1, 2, 3, 4, 5 ); cout << endl; 

Predictably (according to my understanding of C ++ syntax), only one of the values โ€‹โ€‹was fixed by the operator <<

 Just commas: 1 Commas in parentheses: 5 

So the title of the question.

+7
c ++ initialization operator-overloading eigen
source share
3 answers

The basic idea is to overload both << and k , operator.

m << 1 overloaded to put 1 in m and then returns a special proxy object - name it p - containing a link to m .

Then p, 2 overloaded to put 2 in m and return p , so p, 2, 3 first put 2 in m and then 3 .

A similar technique is used with Boost.Assign , although they use += rather than << .

+15
source share

This is a possible simplified implementation.

 struct M3f { double m[3][3]; struct Loader { M3f& m; int i; Loader(M3f& m, int i) : m(m), i(i) {} Loader operator , (double x) { mm[i/3][i%3] = x; return Loader(m, i+1); } }; Loader operator<<(double x) { m[0][0] = x; return Loader(*this, 1); } }; 

The idea is that << returns a Loader instance that is waiting for the second element, and each loader instance uses a comma operator to update the matrix and returns another loader instance.

Note that overloading the operator with a comma is usually considered a bad idea, since the most characteristic characteristic of the operator is the strict evaluation order from left to right. However, during overload this is not guaranteed and, for example, in

 m << f(), g(), ... 

g() can be called before f() .

Please note that I'm talking about the evaluation order, not about associativity or priority, which, of course, is also supported for overloaded versions. For example, g() can be called before f() , but the result from f() guaranteed to be placed in the matrix before the result from g() .

+7
source share

The comma itself is an operator in C ++, which can be overloaded (and, apparently, in its own way). I donโ€™t know how to correctly implement the overload function, but Iโ€™m sure that you can search for sources of your own search to find them.

For your little experiment, you should understand how an operator with an unloaded comma works in C ++.

The comma operator has the form <statement>,<statement> and is evaluated regardless of what the second operator is evaluated for. The operator << has a higher priority than the operator,. Because of this, cout is evaluated before the rest of the comma operations are processed.

Since , is an association from left to right, the code (1,2,3,4,5) is ((((1,2),3),4),5) , which calculates the most correct value, which is 5 .

+2
source share

All Articles