When to overload Comma Operator?

I so often see questions about SO about overloading a comma operator in C ++ (mainly not related to overloading, but, for example, the concept of sequence points), and this makes me wonder:

When should you overload a comma? What are some examples of its practical use?

I just can't think of any examples from my head where I saw or needed something like

foo, bar; 

in real code, so I wonder when (if ever) it is actually used.

+53
c ++ function operator-overloading
Apr 09 2018-11-11T00:
source share
10 answers

Change the focus slightly to:

When do you overload a comma?

Answer: Never.

Exception: if you are doing metaprogramming of a template, operator, has a special place at the very bottom of the operator's priority list, which can be useful for building SFINAE protection devices, etc.

Only two practical applications that I saw while overloading operator, , are in Boost :

+56
Apr 09 2018-11-11T00:
source share

I used the comma operator to index maps with multiple indices.

 enum Place {new_york, washington, ...}; pair<Place, Place> operator , (Place p1, Place p2) { return make_pair(p1, p2); } map< pair<Place, Place>, double> distance; distance[new_york, washington] = 100; 
+99
Aug 08 '13 at 21:19
source share

Boost.Assign uses it so you can do things like:

 vector<int> v; v += 1,2,3,4,5,6,7,8,9; 

And I saw how it was used for fancy language hacks, I will see if I can find them.




Yeah, I remember one of these bizarre uses: collecting multiple expressions . (Warning, dark magic.)

+30
Apr 09 2018-11-11T00:
source share

The comma has an interesting property because it can take a parameter of type void . If so, then the built-in comma operator is used.

This is useful if you want to determine if an expression is of type void:

 namespace detail_ { template <typename T> struct tag { static T get(); }; template <typename T, typename U> tag<char(&)[2]> operator,(T, tag<U>); template <typename T, typename U> tag<U> operator,(tag<T>, tag<U>); } #define HAS_VOID_TYPE(expr) \ (sizeof((::detail_::tag<int>(), \ (expr), \ ::detail_::tag<char>).get()) == 1) 

I let the reader understand what was going on. Remember that operator, bound to the right.

+20
Aug 11 2018-11-21T00:
source share

Like the @GMan Boost.Assign example , Blitz ++ overloads the comma operator to provide convenient syntax for working with multidimensional arrays. For example:

 Array<double,2> y(4,4); // A 4x4 array of double y = 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1; 
+12
Apr 09 2018-11-11T00:
source share

In SOCI, the C ++ Database Access Library is used to implement the incoming part of the interface:

 sql << "select name, salary from persons where id = " << id, into(name), into(salary); 

From frequently asked questions :

Q: The overloaded comma operator is just obfuscation, I don't like it.

Well, consider the following:

"Send the request X to server Y and put the result in the variable Z."

Above, "and" plays the role of a comma. Even if comma overloading is not a very popular practice in C ++, some libraries do this in order to achieve a concise and easily trained syntax. We are sure that in SOCI the comma operator was heavily loaded.

+9
Mar 14 '13 at 19:28
source share

One option is Boost Assign (although I'm sure some people will consider this abuse rather than good use).

Boost Spirit probably also overloads the operator with a comma (it overloads almost everything else ...)

+6
Apr 09 '11 at 0:50
source share

At the same time, a request was sent to me on github pull with a comma operator overload. It looked like this

 class Mylogger { public: template <typename T> Mylogger & operator,(const T & val) { std::cout << val; return * this; } }; #define Log(level,args...) \ do { Mylogger logv; logv,level, ":", ##args; } while (0) 

then in my code I can do:

  Log(2, "INFO: setting variable \", 1, "\"\n"); 

Can someone explain why this is a good or bad use case?

+4
Dec 31 '13 at 20:38
source share

One practical use is to use it effectively with variable arguments in a macro. By the way, variable arguments were previously extensions to GCC and are now part of the C ++ 11 standard.

Suppose we have a class X that adds an object of type A . i.e.

 class X { public: X& operator+= (const A&); }; 

What if we want to add 1 or more objects A to X buffer; ?
For example,

 #define ADD(buffer, ...) buffer += __VA_ARGS__ 

Above the macro, if used as:

 ADD(buffer, objA1, objA2, objA3); 

then it will expand to:

 buffer += objA1, objeA2, objA3; 

Therefore, this will be a great example of using the comma operator, since variable arguments expand with the same.

So, to resolve this, we overload the comma operator and wrap it around += , as shown below

  X& X::operator, (const A& a) { // declared inside `class X` *this += a; // calls `operator+=` } 
+3
Aug 3 '14 at 22:13
source share

Here is an example from the OpenCV documentation ( http://docs.opencv.org/modules/core/doc/basic_structures.html#mat ). The comma operator is used to initialize cv :: Mat:

 // create a 3x3 double-precision identity matrix Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); 
+1
May 20 '14 at 14:06
source share



All Articles