How many people knew C++ let's you overload the comma operator?
#include <iostream.h>
class A
{
public:
void operator , (int i)
{
cout << "Overloaded Comma operator" << endl;
};
};
void main()
{
A a;
a, 1;
}
Apparently this was mainly done to preserve orthogonality. ("All the other operators are doing it")
Of course "," has such a low operator prescedence that you pretty much need to use parenthesis to force the compiler to use it. Probably a good thing though, especially when you think of function calls. (Those commas aren't operators, merely punctuation). Anyways, the following code would be treated differently.
Func(b,c); // Normal function call
Func((b,c)); // Invokes the comma operator, and the uses the result for the function parameter
Where the comma is an operator, is in for loops.
for (i = 0, j = 100; i < 100; i++, j--)
According to the C++ spec, the comma operator evaluates expressions in a left to right order, and then returns the value of the right-most expression. Which of course means evaluating the expression(s) on the left had better cause a side effect, or it's completely useless. Here's a useless example:
int i;
i = 1,2;
cout << i << endl;
i = (1, 2);
cout << i << endl;
The output is:
Why? Because the = operator has a higher prescedence than the comma operator. Keep in mind that i = 1 is an expression in it's own right (and it's value is one). It gets evaluated before the 2 is evaluated. The result of the entire expression is then 2, which is thrown away.
The only place anyone every really uses the comma operator is in for loops, and they always seem to use them for side effects only, and not for returning values. Here's a potential example from the C++ specs on how it could be used to return a value:
This will pass 5 to the function, but the variable t will be assigned the value 3.
The only real use I was able to find for actually overloading the comma operator, is initializing variables without using the construction name. Example:
To get this to work, however, you have to also overload the = operator. Remember the prescedence rules. It is basically the expression ((d = 1), 2). What you can do is have the = operator return a reference to the object, which the , 2 operator can be applied to.
class D
{
public:
D& operator = (int i)
{
cout << "= operator" << i << endl;
return *this;
};
D& operator , (int i)
{
cout << ", operator" << i << endl;
return *this;
};
}
I suppose you could use this if you wanted to obsfucate some code. Like how macros like to put () around everything, but even then it still looks different. Well, at least overloading it can screw up the order of evaluation. Instead of evaluating from left to right, it becomes function calls, which have whatever order of evaluation the compiler feels like. This is at least evident for globally overloaded operators, which actually have two parameters instead of one. So
would be like
which might evaluate from right to left.