By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,483 Members | 1,052 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,483 IT Pros & Developers. It's quick & easy.

Confused about the comma operator

P: n/a
I came upon the idea of writting a logging class that
uses a Python-ish syntax that's easy on the eyes (IMO):

int x = 1;
double y = 2.5;
std::string z = "result";

debug = "Results:", x, y, z;

The above example outputs:

Results: 1 2.5 result

The implementation uses a template comma operator and a
template operator= to kick things off. Here is a very
minimal implementation:

struct Value
{
template<typename T>
Value(const T& x)
{ std::cout << x << ' '; }

template<typename U>
Value operator,(const U& y)
{ return Value(y); }
};

struct Log{
template<typename T>
Value operator=(const T& x)
{ return Value(x); }
} debug;

It works, but now that I think about it, I'm not sure
WHY it works. Does it work because the operator= has
higher precedence than the comma operator, so the
compiler sees it like this:

(debug = "Results:"), x, y, z;

Of course operator= returns a Value object which
displays "Result" and (thanks to the template comma
operator) keeps the chain going in the normal
left-to-right evaluation order?

If this is the case, then I find it counter-intuitive
because the type and value of an expression in the form
(e1,e2) is e2. I find this behavior a bit surprising
and inconsistent:

void print(int i)
{ std::cout << i << '\n'; };

int w;
w = 1, 2; // w = 1
print(w); // prints 1
print((1,2)); // prints 2
Jul 22 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Sun, 11 Apr 2004 15:38:18 -0400, Derek <an*******@cheese.com> wrote:
It works, but now that I think about it, I'm not sure
WHY it works. Does it work because the operator= has
higher precedence than the comma operator, so the
compiler sees it like this:

(debug = "Results:"), x, y, z;
Right.

Of course operator= returns a Value object which
displays "Result" and (thanks to the template comma
operator) keeps the chain going in the normal
left-to-right evaluation order?
Sure.

If this is the case, then I find it counter-intuitive
because the type and value of an expression in the form
(e1,e2) is e2. I find this behavior a bit surprising
and inconsistent:

void print(int i)
{ std::cout << i << '\n'; };

int w;
w = 1, 2; // w = 1
print(w); // prints 1
print((1,2)); // prints 2


The evaluation order of the comma operator is fixed as left-to-right; this
is more than a simple associativity rule, as in the case of, say, the
additive operators where
a + b
give the compiler the freedom to evaluate either a or b first (or both
simultaneously). Since the order of evaluation of the comma operator /is/
fixed, it makes the most sense to have the value of the result be the value
of the last operand evaluated; otherwise the compiler might have to do
extra work to "push" the value of the left-most operand before evaluating
the rest, and then "pop" that value afterwards.
-leor
--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: Download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #2

P: n/a
Leor Zolman wrote:
Since the order of evaluation of the comma operator
/is/ fixed, it makes the most sense to have the
value of the result be the value of the last operand
evaluated; otherwise the compiler might have to do
extra work to "push" the value of the left-most
operand before evaluating the rest, and then "pop"
that value afterwards


That makes sense and I find the left-to-right behavior
of the comma operator perfectly sensible. I just
think that the fact that it has the lowest precedence
of all operators can lead to unexpected behavior. To
repeat my simple example:

int x;
x = 1,2; // x is 1

I would expect x to be 2 because of the left-to-right
evaluation of the comma operator, but here op= takes
precedence.
Jul 22 '05 #3

P: n/a
On Sun, 11 Apr 2004 18:41:35 -0400, Derek <an*******@cheese.com> wrote:
Leor Zolman wrote:
Since the order of evaluation of the comma operator
/is/ fixed, it makes the most sense to have the
value of the result be the value of the last operand
evaluated; otherwise the compiler might have to do
extra work to "push" the value of the left-most
operand before evaluating the rest, and then "pop"
that value afterwards


That makes sense and I find the left-to-right behavior
of the comma operator perfectly sensible. I just
think that the fact that it has the lowest precedence
of all operators can lead to unexpected behavior. To
repeat my simple example:

int x;
x = 1,2; // x is 1

I would expect x to be 2 because of the left-to-right
evaluation of the comma operator, but here op= takes
precedence.


One thing Java got right, IMHO, was to limit the use of the comma operator
to the "init" and "incr" portions of for loops. This would have eliminated
an awful lot of grief wrt the comma operator's precedence in C and C++. I
learned early on to always think of it as "the lowly comma operator," as a
mental cue to not lose track of its precedence whenever I encountered its
use in expressions other than as part of the aforementioned 'for' loop
constructs. It took the emergence of Stupid Template Tricks such as yours
(and I use the term affectionately, /not/ disparagingly) and Thorsten
Ottosen's initialization library:

http://www.codeproject.com/vcpp/stl/PGIL.asp?print=true

to finally give the comma operator some good reason for existence other
than "for" loop management.
-leor

--
Leor Zolman --- BD Software --- www.bdsoft.com
On-Site Training in C/C++, Java, Perl and Unix
C++ users: Download BD Software's free STL Error Message Decryptor at:
www.bdsoft.com/tools/stlfilt.html
Jul 22 '05 #4

P: n/a
Leor Zolman <le**@bdsoft.com> wrote:
One thing Java got right, IMHO, was to limit the use of the comma operator
to the "init" and "incr" portions of for loops. This would have eliminated
an awful lot of grief wrt the comma operator's precedence in C and C++.
[ ... ]
to finally give the comma operator some good reason for existence other
than "for" loop management.


I have found some other occasional uses for it:

1. In preprocessor macros, to enable them to act like functions with a
return value (and to avoid the do..while(0) construct)

2. To return an error code and also perform error logging, concisely:
if (FAILED(foo()))
return do_log(whatever), ERR_FOO_FAILED;

Admittedly these are C-based uses that can probably be superseded
by more natural C++ constructs.

Also, in the same vein as 2, sometimes if my actions to perform in a
block after an "if" or "else" are concise, or conceptually one action
that requires 2 statements, I will write "a, b;" instead of going to
4 lines by using curly braces and a semicolon.
Jul 22 '05 #5

P: n/a
Old Wolf wrote:
I have found some other occasional uses for it:

1. In preprocessor macros, to enable them to act like functions with a
return value (and to avoid the do..while(0) construct)
Using the preprocessor for this kind of thing is almost always VERY BAD.

2. To return an error code and also perform error logging, concisely:
if (FAILED(foo()))
return do_log(whatever), ERR_FOO_FAILED;
This is silly. No, on second thought it is stupid.

if (FAILED(foo)) {
do_log(whatever);
return ERR_FOO_FAILED;
}

Also, see below.
Admittedly these are C-based uses that can probably be superseded
by more natural C++ constructs.

Also, in the same vein as 2, sometimes if my actions to perform in a
block after an "if" or "else" are concise, or conceptually one action
that requires 2 statements, I will write "a, b;" instead of going to
4 lines by using curly braces and a semicolon.


What is with this whole "It's more concise (i.e., better) if I squeeze
it all on one line!" thing that so many programmers seem to have a
religious belief in? If you MUST do this kind of junk:

if (FAILED(foo)) { do_log(whatever); return ERR_FOO_FAILED; }

There! It's better than your two line thing 'cause it's only one line
right?
Jul 22 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.