Topic: Post Increment/decrement operator suggestion.


Author: Bart.van.Ingen.Schenau@ict.nl (Bart van Ingen Schenau)
Date: Tue, 15 Jul 2003 03:01:27 +0000 (UTC)
Raw View
On Fri, 11 Jul 2003 17:49:40 +0000 (UTC), dhruvbird@gmx.net ("Dhruv")
wrote:

>
>Now, I'd like to confirm something:
>1. "> No, the operator<< does not introduce a sequence point.
>> And the sequence points introduced by a function call and return do not
>> apply the the entire expression, but only to respectively the arguments
>> of the function being called and the use of the return value."
>
>By this you mean that the arguments of a function, like operator<<(cout,
>b) have to be evaluated before the function call, but the order in which
>this happens is unspecified by the above, but the return value will
>be obtained ONLY after the evaluation of the function, that is at the end
>of the function sequence point. This has got nothing to do with the full
>expression.
>
>And, while finding out what will be evaluated in the full expression, we
>consider the sequence points to be at the beginning and end of that full
>expression. Like this:
>*operator<<3(operator<<2(operator<<1(cout, b), foo(b++)), endl);*
>Where, the '*' denotes the sequence point.
>
>Similarly, if we wanted to find out the order of evaluation of foo (b++)
>and <<2 wrt each other, we have to mark the sequence points as such:
>
>*operator<<3*(operator<<2*(operator<<1(*cout*, *b*)*, *foo(b++)*)*, *endl*);*
>
>So, basically, we can never in such cases (where function calls are
>embedeed within each other) determine the order of evaluation of
>individual function parameters wrt each other right?
>
>So, for operator<<3 (arg1, arg2). If arg1, and arg2 are both function
>calls, then which is evaluated first is not specified, but if arg1 =
>foo(bar (23, 56), 45), and arg2 = bar (12, 99), then, it is specified that
>bar(23, 56) will be evaluated before foo (bar(), 45), but still the order
>of bar (23, 56) is unspecified wrt. bar (12, 99), because the order of
>arg1, wrt arg2 is unspecified.
>
>Am I right here?

Yes, you are completely right.

>On Thu, 10 Jul 2003 03:44:42 +0000, Bart van Ingen Schenau wrote:
>
>>On Wed, 9 Jul 2003 02:42:24 +0000 (UTC), dhruvbird@gmx.net ("Dhruv")
>>wrote:
>>>, so we have to
>>>access the value of 'b' in the full expression only once, and that too
>>>only so that we can modify. Here, it is being used twice, once to modify
>>>it, and once by cout. Or is it that we can access the value only once
>>>between the sequence points?
>>
>> You can access multiple times between sequence points, otherwise an
>> expression like 'b+b' would be invalid.
>>
>>
>Sorry, I meant access it only once if it is being modified, and that
>access should be only to read the value. (to be modified).

Yes, that is correct.
In fact, you used almost the same wording as the standard does. :-)

>>
>
>Regards,
>-Dhruv.
>
Bart v Ingen Schenau

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Wed, 16 Jul 2003 16:47:29 +0000 (UTC)
Raw View
On Tue, 15 Jul 2003 03:01:27 +0000, Bart van Ingen Schenau wrote:
[snip]......

>>Am I right here?
>
> Yes, you are completely right.
>
[snip]......

>>Sorry, I meant access it only once if it is being modified, and that
>>access should be only to read the value. (to be modified).
>
> Yes, that is correct.
> In fact, you used almost the same wording as the standard does. :-)
>

Thanks a lot :-)



Regards,
-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Fri, 11 Jul 2003 01:36:43 +0000 (UTC)
Raw View
In article <3f0c2be6$0$87927$9a6e19ea@news.newshosting.com>, Ron Natalie
<ron@sensor.com> writes
>> t.add_hrs(add (23, 56)).add_min (add (34, 49)).add_sec(sub (23, 12));
>>
>> So, here, it is not specified whether add (23, 56) is called first, or add
>> (34, 49) or sub(23, 12) is called first?
>
>That is correct.

True, but note that that does not apply to add_hrs(), add_min() and
add_sec().

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Fri, 11 Jul 2003 06:13:14 +0000 (UTC)
Raw View
On Wed, 09 Jul 2003 21:57:42 +0000, Bo Persson wrote:

> [snip]......

>> Ok, so this is invalid, because:
>>
>> 1. The order of evaluation of the expressions is unspecified.
>>
>> 2. Here, the sequence points are the << operators. Right?,
>
> No, the sequence point I was talking about is the one at the end of
> the full-expression. In this case, when you reach the semi-colon
> everything must be evaluated and the side effects must all be
> completed.
>
> There are also sequence points for the *parameters* before each
> individual function call, but they don't affect the full expression.
>
>>so we have to
>> access the value of 'b' in the full expression only once, and that
> too
>> only so that we can modify. Here, it is being used twice, once to
> modify
>> it, and once by cout. Or is it that we can access the value only
> once
>> between the sequence points?
>
> You can read b any number of times in one expression if it is only
> read, but *if* it is updated that must be the only access.
>

Thanks.


>> "9)  The sequence point at the function return is not explicitly
> speci-
>>   fied in ISO C, and can be considered redundant with sequence
> points at
>>   full-expressions,  but the extra clarity is important in C++.  In
> C++,
>>   there are more ways in which a called function can terminate its
> exe-
>>   cution, such as the throw of an exception."
>
> The function return actions have to do with what happens to any
> objects created inside the function. In C they are just discarded, but
> in C++ there might be destructors for these objects that must run at
> function return. It does not affect us here.
>

Ok.


>> So, am I right about the sequence points being at the place where
> the
>> operator<< is seen? Or is it unspecified, because the function
> return is
>> being used here? If not, where is it specified?
>
> The sequence point is at the end of the full-expression, at the
> semi-colon. The functions have their own sequence points, but they are
> not important here.
>
>>
>> "8 The order of evaluation of arguments is unspecified.  All side
> effects
>>   of argument expression evaluations take effect before the function
> is
>>   entered.   The  order  of evaluation of the postfix expression and
> the
>>   argument expression list is unspecified."
>>
>> Does this apply here? So, what it's trying to say is that the order
> in
>> which the postfix expressions may be evaluated is unspecified?
>
> The postfix expression for a function call is the list of expressions
> making up the parameters. In a function f(x, y) we do not know whether
> x or y is evaluated first, just that they are both evaluated before
> the function call. If you write this f(x++, x++) you are in trouble!
> :-)
>
> If you have a call f(x + a + b, y + a + b) the compiler can evaluate
> a+b only once, and reuse the result. That makes it hard to tell which
> parameter is actually evaluated first, because they have some parts in
> common.
>
> In your case we have something like f(g(x + a + b), y + a + b). Here
> we know that g() must be called before f(), but we cannot tell whether
> y + a + b is evaluated before or after the call to g(), or a litte of
> each.
>

Ok, got it. :-)

[snip]......
> Yes.
>
>> However, function return is used to evaluate the full expression. I
> think that
>> add_hrs will be called first, then add_min, and then add_sec, but
> cannot
>> find any proof in the standard that says anything about it? Am I
> right
>> here?
>
> Yes, you are.
>
> The proof is indirect in that member functions need the hidden 'this'
> parameter from the caller. The compiler transforms t.add_hrs(h) into
> struct_type::add_hrs(&t, h), where &t will be the value of 'this'
> inside the function. From this we can tell that the expression before
> the dot must be evaluated before the function call, as it is a
> parameter.
>

Ok.

Regards,
-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Fri, 11 Jul 2003 17:49:40 +0000 (UTC)
Raw View
On Thu, 10 Jul 2003 03:44:42 +0000, Bart van Ingen Schenau wrote:
[snip]......


>>Let's see if I got it right now. I'm writing down what I have gathered
>>from all this:
>>
>>cout<<b<<foo (b++)<<endl;
>>
>>"Except where noted, the order of evaluation of operands of  individual
>>  operators  and subexpressions of individual expressions, and the order
>>  in which side effects take place, is unspecified.  Between the  previ-
>>  ous  and  next  sequence  point  a scalar object shall have its stored
>>  value modified at most once by the evaluation of an expression.   Fur-
>>  thermore,  the  prior  value  shall  be accessed only to determine the
>>  value to be stored.  The requirements of this paragraph shall  be  met
>>  for  each  allowable  ordering of the subexpressions of a full expres-
>>  sion; otherwise the behavior is undefined."
>>
>>Ok, so this is invalid, because:
>>
>>1. The order of evaluation of the expressions is unspecified.
>
> Correct.
>
>
>>2. Here, the sequence points are the << operators. Right?
>
> No, the operator<< does not introduce a sequence point. And the sequence
> points introduced by a function call and return do not apply the the
> entire expression, but only to respectively the arguments of the
> function being called and the use of the return value.
>
> If we add numbers to the << operators for easy reference, the rules
> imposed by the sequence points are:
>
> In the statement
>   cout <<1 b <<2 foo(b++) <<3 endl;
>
> - cout and b must be evaluated before <<1
> - b++ must be evaluated before
> the call to foo()
> - foo(b++) and <<1 must be evaluated before <<2
> - <<2 and endl must be evaluated before <<3
> - There is no ordering requirement on b, b++ and endl with respect to each other.
> - There is no ordering requirement on b, foo(b++) and endl with respect
> to each other.
>
> This can be made visual by writing the statement as nested function
> calls:
>   operator<<3(operator<<2(operator<<1(cout, b), foo(b++)), endl);

This above line REALLY helped me understand the stuff above. It seems much
more like home now :-) Ok, so in the above expression, only partial
ordering is specified, as you have mentioned.



Now, I'd like to confirm something:
1. "> No, the operator<< does not introduce a sequence point.
> And the sequence points introduced by a function call and return do not
> apply the the entire expression, but only to respectively the arguments
> of the function being called and the use of the return value."

By this you mean that the arguments of a function, like operator<<(cout,
b) have to be evaluated before the function call, but the order in which
this happens is unspecified by the above, but the return value will
be obtained ONLY after the evaluation of the function, that is at the end
of the function sequence point. This has got nothing to do with the full
expression.

And, while finding out what will be evaluated in the full expression, we
consider the sequence points to be at the beginning and end of that full
expression. Like this:
*operator<<3(operator<<2(operator<<1(cout, b), foo(b++)), endl);*
Where, the '*' denotes the sequence point.

Similarly, if we wanted to find out the order of evaluation of foo (b++)
and <<2 wrt each other, we have to mark the sequence points as such:

*operator<<3*(operator<<2*(operator<<1(*cout*, *b*)*, *foo(b++)*)*, *endl*);*

So, basically, we can never in such cases (where function calls are
embedeed within each other) determine the order of evaluation of
individual function parameters wrt each other right?

So, for operator<<3 (arg1, arg2). If arg1, and arg2 are both function
calls, then which is evaluated first is not specified, but if arg1 =
foo(bar (23, 56), 45), and arg2 = bar (12, 99), then, it is specified that
bar(23, 56) will be evaluated before foo (bar(), 45), but still the order
of bar (23, 56) is unspecified wrt. bar (12, 99), because the order of
arg1, wrt arg2 is unspecified.

Am I right here?




> The only explicit requirement here is that some time before the call to
> a function, the arguments to that function must have been evaluated.
>
>
Ok.

>>, so we have to
>>access the value of 'b' in the full expression only once, and that too
>>only so that we can modify. Here, it is being used twice, once to modify
>>it, and once by cout. Or is it that we can access the value only once
>>between the sequence points?
>
> You can access multiple times between sequence points, otherwise an
> expression like 'b+b' would be invalid.
>
>
Sorry, I meant access it only once if it is being modified, and that
access should be only to read the value. (to be modified).


>>"9)  The sequence point at the function return is not explicitly speci-
>>  fied in ISO C, and can be considered redundant with sequence points at
>>  full-expressions,  but the extra clarity is important in C++.  In C++,
>>  there are more ways in which a called function can terminate its  exe-
>>  cution, such as the throw of an exception."
>>
>>So, am I right about the sequence points being at the place where the
>>operator<< is seen? Or is it unspecified, because the function return is
>>being used here? If not, where is it specified?
>
> As explained above, the order is partially specified.
>
>
Yes.


>>"8 The order of evaluation of arguments is unspecified.  All side
>>effects
>>  of argument expression evaluations take effect before the function  is
>>  entered.   The  order  of evaluation of the postfix expression and the
>>  argument expression list is unspecified."
>>
>>Does this apply here? So, what it's trying to say is that the order in
>>which the postfix expressions may be evaluated is unspecified?
>
> The requirement is in effect here, but it does not affect the outcome
> for the statement in question.
> The postfix expression referenced in the quote above is in this case the
> function name, respectively the operator name.
>
>
>>And, as Bo Persson said, that the compiler will evaluate the parameters
>>before the functions call, but if there are multiple function calls in
>>the full expression, then there is no guaranrtee that the parameters for
>>one will be evaluated before the the other? So, is it somehitng like:
>>
>>Suppose time is a "time" class, and t is an object of time.
>>
>>t.add_hrs(add (23, 56)).add_min (add (34, 49)).add_sec(sub (23, 12));
>>
>>So, here, it is not specified whether add (23, 56) is called first, or
>>add (34, 49) or sub(23, 12) is called first? Have I understood it right?
>>However, function return is used to evaluate the full expression. I
>>think that add_hrs will be called first, then add_min, and then add_sec,
>>but cannot find any proof in the standard that says anything about it?
>>Am I right here?
>
> You are right.
> The reason that the functions add_hrs(), add_min() and add_sec() must be
> called in that order is because add_min() operates on the object
> returned by add_hrs() and there is no requirement that add_hrs() returns
> t (or even an object of class time). The same argument holds for
> add_min() and add_sec().
>
>
Thanks.


Regards,
-Dhruv.

p.s. I must James Kanze for mentioning in one of his replies: :-)
The program is not legal C++, and the standard imposes no requirements
as to what the compiler does with it.

Otherwise I would have never found this out, not to mention the trouble I
caused to James :-)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Wed, 9 Jul 2003 02:42:24 +0000 (UTC)
Raw View
On Mon, 07 Jul 2003 01:14:06 +0000, James Kanze wrote:

> dhruvbird@gmx.net ("Dhruv") writes:
>
> |>  On Thu, 03 Jul 2003 23:48:24 +0000, Ron Natalie wrote:
>
> |>  > You modify b and use it for purposes other than that
> |>  > modification between sequence points.  You have to look at all
> |>  > the allowable orderings.  The compiler is perfectly free to
> |>  > evalutate the first b and the b++ expression before calling any
> |>  > of the function calls.
>
> |>  Ok, so what you are saying is that the compiler may/may not
> |>  evaluate b++ before putting b on the stream? Did I get that right?
>
> No.  What he is saying is that your program is illegal.  But because
> it involves undefined behavior, the compiler is not required to emit a
> diagnostic -- in fact, there exist no requirements what so ever as to
> what the compiler does.
>
> |>  Ok, which section/para in the steandard is all this input coming
> |>  from. I searched, but could only find: 5.2.2 which is function
> |>  call. I was looking for what James Kanze has quoted, about the
> |>  side effects of the expressions...... Where is it?
>
> See my other posting.  Plus, of course, 1.9, which defines sequence
> points and the required behavior of a program relative to them.



Let's see if I got it right now. I'm writing down what I have gathered
from all this:

cout<<b<<foo (b++)<<endl;

"Except where noted, the order of evaluation of operands of  individual
  operators  and subexpressions of individual expressions, and the order
  in which side effects take place, is unspecified.  Between the  previ-
  ous  and  next  sequence  point  a scalar object shall have its stored
  value modified at most once by the evaluation of an expression.   Fur-
  thermore,  the  prior  value  shall  be accessed only to determine the
  value to be stored.  The requirements of this paragraph shall  be  met
  for  each  allowable  ordering of the subexpressions of a full expres-
  sion; otherwise the behavior is undefined."

Ok, so this is invalid, because:

1. The order of evaluation of the expressions is unspecified.

2. Here, the sequence points are the << operators. Right?, so we have to
access the value of 'b' in the full expression only once, and that too
only so that we can modify. Here, it is being used twice, once to modify
it, and once by cout. Or is it that we can access the value only once
between the sequence points?


"9)  The sequence point at the function return is not explicitly speci-
  fied in ISO C, and can be considered redundant with sequence points at
  full-expressions,  but the extra clarity is important in C++.  In C++,
  there are more ways in which a called function can terminate its  exe-
  cution, such as the throw of an exception."

So, am I right about the sequence points being at the place where the
operator<< is seen? Or is it unspecified, because the function return is
being used here? If not, where is it specified?

"8 The order of evaluation of arguments is unspecified.  All side effects
  of argument expression evaluations take effect before the function  is
  entered.   The  order  of evaluation of the postfix expression and the
  argument expression list is unspecified."

Does this apply here? So, what it's trying to say is that the order in
which the postfix expressions may be evaluated is unspecified?

And, as Bo Persson said, that the compiler will evaluate the parameters
before the functions call, but if there are multiple function calls in
the full expression, then there is no guaranrtee that the parameters for one will be
evaluated before the the other? So, is it somehitng like:

Suppose time is a "time" class, and t is an object of time.

t.add_hrs(add (23, 56)).add_min (add (34, 49)).add_sec(sub (23, 12));

So, here, it is not specified whether add (23, 56) is called first, or add
(34, 49) or sub(23, 12) is called first? Have I understood it right?
However, function return is used to evaluate the full expression. I think that
add_hrs will be called first, then add_min, and then add_sec, but cannot
find any proof in the standard that says anything about it? Am I right
here?

Regards,
-Dhruv.









---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: bop2@telia.com ("Bo Persson")
Date: Wed, 9 Jul 2003 21:57:42 +0000 (UTC)
Raw View
""Dhruv"" <dhruvbird@gmx.net> skrev i meddelandet
news:pan.2003.07.08.05.20.30.782471@gmx.net...
> On Mon, 07 Jul 2003 01:14:06 +0000, James Kanze wrote:
>
> > dhruvbird@gmx.net ("Dhruv") writes:
> >
> > |>  On Thu, 03 Jul 2003 23:48:24 +0000, Ron Natalie wrote:
> >
> > |>  > You modify b and use it for purposes other than that
> > |>  > modification between sequence points.  You have to look at
all
> > |>  > the allowable orderings.  The compiler is perfectly free to
> > |>  > evalutate the first b and the b++ expression before calling
any
> > |>  > of the function calls.
> >
> > |>  Ok, so what you are saying is that the compiler may/may not
> > |>  evaluate b++ before putting b on the stream? Did I get that
right?
> >
> > No.  What he is saying is that your program is illegal.  But
because
> > it involves undefined behavior, the compiler is not required to
emit a
> > diagnostic -- in fact, there exist no requirements what so ever as
to
> > what the compiler does.

To put it another way, the compiler is not required to handle cases
where a value is both updated and read in the same expression.
Whatever it does is ok, because the contract between the compiler and
the programmer is broken, and all deals are off.

In this simpler case, the compiler *could* have warned you about the
problem, just to be nice. In the general case, like when b++ is found
in one of the functions called, maybe in another source file that
isn't compiled yet, the compiler cannot know, so it was decided not to
require a diagnostic.

> >
> > |>  Ok, which section/para in the steandard is all this input
coming
> > |>  from. I searched, but could only find: 5.2.2 which is function
> > |>  call. I was looking for what James Kanze has quoted, about the
> > |>  side effects of the expressions...... Where is it?
> >
> > See my other posting.  Plus, of course, 1.9, which defines
sequence
> > points and the required behavior of a program relative to them.
>
>
>
> Let's see if I got it right now. I'm writing down what I have
gathered
> from all this:
>
> cout<<b<<foo (b++)<<endl;
>
> "Except where noted, the order of evaluation of operands of
individual
>   operators  and subexpressions of individual expressions, and the
order
>   in which side effects take place, is unspecified.  Between the
previ-
>   ous  and  next  sequence  point  a scalar object shall have its
stored
>   value modified at most once by the evaluation of an expression.
Fur-
>   thermore,  the  prior  value  shall  be accessed only to determine
the
>   value to be stored.  The requirements of this paragraph shall  be
met
>   for  each  allowable  ordering of the subexpressions of a full
expres-
>   sion; otherwise the behavior is undefined."
>
> Ok, so this is invalid, because:
>
> 1. The order of evaluation of the expressions is unspecified.
>
> 2. Here, the sequence points are the << operators. Right?,

No, the sequence point I was talking about is the one at the end of
the full-expression. In this case, when you reach the semi-colon
everything must be evaluated and the side effects must all be
completed.

There are also sequence points for the *parameters* before each
individual function call, but they don't affect the full expression.

>so we have to
> access the value of 'b' in the full expression only once, and that
too
> only so that we can modify. Here, it is being used twice, once to
modify
> it, and once by cout. Or is it that we can access the value only
once
> between the sequence points?

You can read b any number of times in one expression if it is only
read, but *if* it is updated that must be the only access.


>
>
> "9)  The sequence point at the function return is not explicitly
speci-
>   fied in ISO C, and can be considered redundant with sequence
points at
>   full-expressions,  but the extra clarity is important in C++.  In
C++,
>   there are more ways in which a called function can terminate its
exe-
>   cution, such as the throw of an exception."

The function return actions have to do with what happens to any
objects created inside the function. In C they are just discarded, but
in C++ there might be destructors for these objects that must run at
function return. It does not affect us here.

>
> So, am I right about the sequence points being at the place where
the
> operator<< is seen? Or is it unspecified, because the function
return is
> being used here? If not, where is it specified?

The sequence point is at the end of the full-expression, at the
semi-colon. The functions have their own sequence points, but they are
not important here.

>
> "8 The order of evaluation of arguments is unspecified.  All side
effects
>   of argument expression evaluations take effect before the function
is
>   entered.   The  order  of evaluation of the postfix expression and
the
>   argument expression list is unspecified."
>
> Does this apply here? So, what it's trying to say is that the order
in
> which the postfix expressions may be evaluated is unspecified?

The postfix expression for a function call is the list of expressions
making up the parameters. In a function f(x, y) we do not know whether
x or y is evaluated first, just that they are both evaluated before
the function call. If you write this f(x++, x++) you are in trouble!
:-)

If you have a call f(x + a + b, y + a + b) the compiler can evaluate
a+b only once, and reuse the result. That makes it hard to tell which
parameter is actually evaluated first, because they have some parts in
common.

In your case we have something like f(g(x + a + b), y + a + b). Here
we know that g() must be called before f(), but we cannot tell whether
y + a + b is evaluated before or after the call to g(), or a litte of
each.

>
> And, as Bo Persson said, that the compiler will evaluate the
parameters
> before the functions call, but if there are multiple function calls
in
> the full expression, then there is no guaranrtee that the parameters
for one will be
> evaluated before the the other? So, is it somehitng like:
>
> Suppose time is a "time" class, and t is an object of time.
>
> t.add_hrs(add (23, 56)).add_min (add (34, 49)).add_sec(sub (23,
12));
>
> So, here, it is not specified whether add (23, 56) is called first,
or add
> (34, 49) or sub(23, 12) is called first? Have I understood it right?

Yes.

> However, function return is used to evaluate the full expression. I
think that
> add_hrs will be called first, then add_min, and then add_sec, but
cannot
> find any proof in the standard that says anything about it? Am I
right
> here?

Yes, you are.

The proof is indirect in that member functions need the hidden 'this'
parameter from the caller. The compiler transforms t.add_hrs(h) into
struct_type::add_hrs(&t, h), where &t will be the value of 'this'
inside the function. From this we can tell that the expression before
the dot must be evaluated before the function call, as it is a
parameter.


>
> Regards,
> -Dhruv.
>

Bo Persson
bop2@telia.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 10 Jul 2003 03:44:03 +0000 (UTC)
Raw View
In article <pan.2003.07.08.05.20.30.782471@gmx.net>, Dhruv
<dhruvbird@gmx.net> writes
>2. Here, the sequence points are the << operators. Right?, so we have to
>access the value of 'b' in the full expression only once, and that too
>only so that we can modify. Here, it is being used twice, once to modify
>it, and once by cout. Or is it that we can access the value only once
>between the sequence points?

Wrong, or at least partially so. Unfortunately despite appearances from
the wording of the C and C++ standards there is not a strict ordering of
sequence points, i.e. they do not provide a sequence of events; they can
be nested so the sequence point at a function call only ensures that the
arguments of the function call have been written back. As all the
arguments for all the functions may be evaluated before any are called
the sequence points at the function calls do not protect the evaluation
of the arguments.

The correct way to look at the evaluation of an expression is to look at
it bottom up and to treat it as if all arguments and reads take place
before any function calls. In addition any writes that are independent
of function calls also take place. If the result is that a value that is
somewhere written in that sequence is also read independently (i.e. not
for the purpose of determining what should be written) of that write
then we have undefined behaviour.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Bart.van.Ingen.Schenau@ict.nl (Bart van Ingen Schenau)
Date: Thu, 10 Jul 2003 03:44:42 +0000 (UTC)
Raw View
On Wed, 9 Jul 2003 02:42:24 +0000 (UTC), dhruvbird@gmx.net ("Dhruv")
wrote:

>On Mon, 07 Jul 2003 01:14:06 +0000, James Kanze wrote:
>
>> dhruvbird@gmx.net ("Dhruv") writes:
>>
>> |>  On Thu, 03 Jul 2003 23:48:24 +0000, Ron Natalie wrote:
>>
>> |>  > You modify b and use it for purposes other than that
>> |>  > modification between sequence points.  You have to look at all
>> |>  > the allowable orderings.  The compiler is perfectly free to
>> |>  > evalutate the first b and the b++ expression before calling any
>> |>  > of the function calls.
>>
>> |>  Ok, so what you are saying is that the compiler may/may not
>> |>  evaluate b++ before putting b on the stream? Did I get that right?
>>
>> No.  What he is saying is that your program is illegal.  But because
>> it involves undefined behavior, the compiler is not required to emit a
>> diagnostic -- in fact, there exist no requirements what so ever as to
>> what the compiler does.
>>
>> |>  Ok, which section/para in the steandard is all this input coming
>> |>  from. I searched, but could only find: 5.2.2 which is function
>> |>  call. I was looking for what James Kanze has quoted, about the
>> |>  side effects of the expressions...... Where is it?
>>
>> See my other posting.  Plus, of course, 1.9, which defines sequence
>> points and the required behavior of a program relative to them.
>
>
>
>Let's see if I got it right now. I'm writing down what I have gathered
>from all this:
>
>cout<<b<<foo (b++)<<endl;
>
>"Except where noted, the order of evaluation of operands of  individual
>  operators  and subexpressions of individual expressions, and the order
>  in which side effects take place, is unspecified.  Between the  previ-
>  ous  and  next  sequence  point  a scalar object shall have its stored
>  value modified at most once by the evaluation of an expression.   Fur-
>  thermore,  the  prior  value  shall  be accessed only to determine the
>  value to be stored.  The requirements of this paragraph shall  be  met
>  for  each  allowable  ordering of the subexpressions of a full expres-
>  sion; otherwise the behavior is undefined."
>
>Ok, so this is invalid, because:
>
>1. The order of evaluation of the expressions is unspecified.

Correct.

>
>2. Here, the sequence points are the << operators. Right?

No, the operator<< does not introduce a sequence point.
And the sequence points introduced by a function call and return do
not apply the the entire expression, but only to respectively the
arguments of the function being called and the use of the return
value.

If we add numbers to the << operators for easy reference, the rules
imposed by the sequence points are:

In the statement
  cout <<1 b <<2 foo(b++) <<3 endl;

- cout and b must be evaluated before <<1
- b++ must be evaluated before the call to foo()
- foo(b++) and <<1 must be evaluated before <<2
- <<2 and endl must be evaluated before <<3
- There is no ordering requirement on b, b++ and endl with respect to
each other.
- There is no ordering requirement on b, foo(b++) and endl with
respect to each other.

This can be made visual by writing the statement as nested function
calls:
  operator<<3(operator<<2(operator<<1(cout, b), foo(b++)), endl);

The only explicit requirement here is that some time before the call
to a function, the arguments to that function must have been
evaluated.

>, so we have to
>access the value of 'b' in the full expression only once, and that too
>only so that we can modify. Here, it is being used twice, once to modify
>it, and once by cout. Or is it that we can access the value only once
>between the sequence points?

You can access multiple times between sequence points, otherwise an
expression like 'b+b' would be invalid.

>
>"9)  The sequence point at the function return is not explicitly speci-
>  fied in ISO C, and can be considered redundant with sequence points at
>  full-expressions,  but the extra clarity is important in C++.  In C++,
>  there are more ways in which a called function can terminate its  exe-
>  cution, such as the throw of an exception."
>
>So, am I right about the sequence points being at the place where the
>operator<< is seen? Or is it unspecified, because the function return is
>being used here? If not, where is it specified?

As explained above, the order is partially specified.

>
>"8 The order of evaluation of arguments is unspecified.  All side effects
>  of argument expression evaluations take effect before the function  is
>  entered.   The  order  of evaluation of the postfix expression and the
>  argument expression list is unspecified."
>
>Does this apply here? So, what it's trying to say is that the order in
>which the postfix expressions may be evaluated is unspecified?

The requirement is in effect here, but it does not affect the outcome
for the statement in question.
The postfix expression referenced in the quote above is in this case
the function name, respectively the operator name.

>
>And, as Bo Persson said, that the compiler will evaluate the parameters
>before the functions call, but if there are multiple function calls in
>the full expression, then there is no guaranrtee that the parameters for one will be
>evaluated before the the other? So, is it somehitng like:
>
>Suppose time is a "time" class, and t is an object of time.
>
>t.add_hrs(add (23, 56)).add_min (add (34, 49)).add_sec(sub (23, 12));
>
>So, here, it is not specified whether add (23, 56) is called first, or add
>(34, 49) or sub(23, 12) is called first? Have I understood it right?
>However, function return is used to evaluate the full expression. I think that
>add_hrs will be called first, then add_min, and then add_sec, but cannot
>find any proof in the standard that says anything about it? Am I right
>here?

You are right.
The reason that the functions add_hrs(), add_min() and add_sec() must
be called in that order is because add_min() operates on the object
returned by add_hrs() and there is no requirement that add_hrs()
returns t (or even an object of class time). The same argument holds
for add_min() and add_sec().

>
>Regards,
>-Dhruv.
>
Bart v Ingen Schenau

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Thu, 10 Jul 2003 03:50:25 +0000 (UTC)
Raw View
""Dhruv"" <dhruvbird@gmx.net> wrote in message news:pan.2003.07.08.05.20.30.782471@gmx.net...

> 2. Here, the sequence points are the << operators. Right?,

The sequqence point is the call to the operator<< function.

> so we have to
> access the value of 'b' in the full expression only once, and that too
> only so that we can modify. Here, it is being used twice, once to modify
> it, and once by cout.

Precisely.    It is possible that the first evaluation of b (for cout) and the
b++ are both executed before either of the operator<< functions (and their
inherent sequence points).

> Or is it that we can access the value only once
> between the sequence points?

No, you can access it as many times as you want provided you don't also modify it.

> So, am I right about the sequence points being at the place where the
> operator<< is seen? Or is it unspecified, because the function return is
> being used here? If not, where is it specified?

It has nothing to do with being "seen."   It has to do when things are executed.

>
> Does this apply here? So, what it's trying to say is that the order in
> which the postfix expressions may be evaluated is unspecified?

Yes, but it applies in that is allows the operator<< calls in your example
expression to be executed in an order that causes both subexpressions
involving b to be invoked before any function call (and the inherent sequence
points).

>
> And, as Bo Persson said, that the compiler will evaluate the parameters
> before the functions call, but if there are multiple function calls in
> the full expression, then there is no guaranrtee that the parameters for one will be
> evaluated before the the other?

Preciesly.

> t.add_hrs(add (23, 56)).add_min (add (34, 49)).add_sec(sub (23, 12));
>
> So, here, it is not specified whether add (23, 56) is called first, or add
> (34, 49) or sub(23, 12) is called first?

That is correct.   And they all can be called before any of the add_hrs, add_min, or add_sec.
On the ohter hand, they can be called at the last possible instance before the value is needed
Two of the possible orderings:

    sub(23,12)
    add(23,56)
    add(34,59)
    add_hrs
    add_min
    add_sec

or

    add(23,56)
    add_hrs
    add(34,49)
    add_min
    sub(23.12)
    add_sec.

> However, function return is used to evaluate the full expression. I think that
> add_hrs will be called first, then add_min, and then add_sec, but cannot
> find any proof in the standard that says anything about it? Am I right
> here?
>
Well, it's pretty hard for the compiler to come up with the return value without
calling the function.   That pretty  much implies that add_hrs has to be called before
add_min etc...


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Wed, 2 Jul 2003 13:53:25 +0000 (UTC)
Raw View
On Mon, 30 Jun 2003 04:32:49 +0000, KIM Seungbeom wrote:


> Anyway, I guess it's to late for such a big change. :-(

The thread was exactly what I was thionking about. Ok, so it's already
been discussed before, and no one wants to change :-( However, there was
one example that was interesting. It was something like in reply to Boris
Formitchev's idea of using a proxy and why not to use it. I feel that the
main culprit is pass by reference. So, if you pass by reference and do a
post-increment in the function call, then the value passed will be
post-incremented. However, if the language was made such that
post-increment was actually what it said, then things would've been much
better. Practically the whole of HP's STL has been written with code like
this:

while (*first++!=*something++) ...and so on. So, instead of changing every
post-increment to a combination of pre-inc. and assignment, it would have
been better, but as you said, I guess it's to late, and people have come
to expect some behaviour of post-inc...... Which cannot be changed in
their minds.

-Dhruv.












---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Wed, 2 Jul 2003 13:53:35 +0000 (UTC)
Raw View
On Tue, 01 Jul 2003 23:44:45 +0000, James Kanze wrote:

> |>  >Look at this code:
>
> |>  >int foo (int x) { return x; }
>
> |>  >int main ()
> |>  >{
> |>  >  int b = 5;
> |>  >  cout<<b<<endl<<foo(b++)<<endl;
> |>  >  cout<<b<<endl;
> |>  >}
>
> |>  >The output is something like:
> |>  >6
> |>  >5
> |>  >6
>
> |>  But you are passing by value, now declare foo as:
>
> |>  int foo(int & x);
>
> |>  and see what you get now.
>
> He still gets undefined behavior.  Except that if foo takes a
> non-const reference, the compiler is required to emit a diagnostic,
> because the result of post-incrementation is not an lvalue.
>
> I'm not sure what point he is trying to make.  The standard seems
> pretty clear to me with regards to the following points:
>
>   - a function call is a sequence point, all side effects of
>     previously evaluated expressions must take place before the
>     function call, and
>
>   - the results of a post-fix incrementation operator is the value of
>     the operand before the incrementation.
>

I agreed with you fully on what you have just said.
Even the example that I gave is proof that what you said is 100% correct.

See the output: 6 5 6. That's cause streams a kinda backwards, so when the
first thing (foo(b++)) is evaluated, foo gets 5, b becomes 6, then b is
put on the stream, because of the reverse nature of streams, and you see b
as 6, which it actually is. Intuituvely, you would expect b to be 5 here,
but it's not.

What point I'm trying to make has been lost (well, not actually). This
post started out as a proposal to have ++(int) behave differently that what
it does now, and it seems that if it is, then many of the things that
people expect form post increment would be lost especially for function
calls, where as you said, the expression should be evaluated before the
function call.


What I said was, well pretty much that this should be allowed:

void foo (int &x);

call foo this way:

int b = 5;
foo (b++);

But, it seems that it would cause a lot of confusion that way, especially
if foo were to modify x inside itself. And oterwise too.


> For the love of me, I can't figure out whether he disagrees with one
> of these points (if so, I'd appreciate some quote from the standard,
> because I've always firmly believed both), or if he hasn't understood
> some part of it.

I got the point that you were trying to make, but a little slowly :-)
Sorry for the trauma caused :-)

Regards,
-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Wed, 2 Jul 2003 13:53:46 +0000 (UTC)
Raw View
On Tue, 01 Jul 2003 23:45:01 +0000, James Kanze wrote:

> dhruvbird@gmx.net ("Dhruv") writes:
>
> |>  On Fri, 27 Jun 2003 17:55:21 +0000, kanz wrote:
> |>
> |>  >> Would you settle for this instead of the current solution?
>
> |>  > I haven't yet figured out what "this" is, so I couldn't say.  I
> |>  > would like to see the order of evaluation somewhat more strictly
> |>  > defined, but I'm not sure what you are proposing.
>
> |>  What I'm proposing is that instead of having operator++(int) being
> |>  viewed as a normal function, which executes code, and returns a
> |>  value, and that value is used as the result, why not have the
> |>  object on which ++(int) is applied be used as the result, and then
> |>  when the expression has finished, execute the code in
> |>  operator++(int).
>
> What do you mean exactly by "when the expression has finished"?  When
> the i++ has finished, or when the complete expression has finished?
> In the first case, you don't change anything with regards to existing
> code; you still need the temporary (although perhaps the compiler
> generates it automatically).

No, not when ++(int) has finished.


In the latter, you've changed the
> semantics of existing legal code -- semantics on which I'm sure more
> than one application depends.

Yes, here. Ok, so I get it, this would be disastrous, something along
these lines:

int b = 5;
int foo (int& x) { return b*x; }

int i = foo (b++);
Ok, i = 6*6 = 36;

Hmmmmmm...... Interesting, so if I want it to work as expected, the
temporary will *have* to be involved......


Thanks :-)
-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Wed, 2 Jul 2003 14:23:38 +0000 (UTC)
Raw View
On Tue, 01 Jul 2003 01:42:30 +0000, William M. Miller wrote:
[snip]...

> -- William M. Miller
>

Thanks,
-Dhruv.







---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Wed, 2 Jul 2003 14:23:53 +0000 (UTC)
Raw View
""Dhruv"" <dhruvbird@gmx.net> wrote in message news:pan.2003.07.02.07.20.30.261686@gmx.net...

>
> No, not when ++(int) has finished.
>

There's no such concept as "expression finishing" in C++.
There is only the concept of sequence points, which there is none
implicit in the application of ++ to int.

What you are techncially asking for is that the inrement opreations
to provide a sequence point.   I think you'll get some argument on that
suggestion.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Thu, 3 Jul 2003 00:40:37 +0000 (UTC)
Raw View
On Fri, 27 Jun 2003 17:55:21 +0000, kanz wrote:

[snip]......

>     int
>     main()
>     {
>         Integer i( 5 ) ;
>         out << i ++ << '\n' ;
>         return 0 ;
>     }
>
> In the distant past, this would display 5.  Today, it is illegal.
>

Do you mean 6? From what you wrote, what I gather is that pre and post
increment had the same function being called, in exactly the same way, am
I right, or have I misunderstood it?

-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Thu, 3 Jul 2003 00:40:38 +0000 (UTC)
Raw View
On Sun, 29 Jun 2003 21:09:38 +0000, James Kanze wrote:

[snip]......


> Could you please indicate what makes you think this.  As far as I can
> tell, the standard is clear.  A function call is a sequence point, and
> the observable results of the program must be as if all of the side
> effects of preceding functions have taken place.
>

The function foo is: int foo (int x) { return x; } It
just returns the value passed, so there is no discrepency with regard to
what was passed to foo().


> |>  As in the function f() will get a parameter of 5, not 6.
>
> The parameter is 5.  The parameter is the value of b before the
> incrementation.  In the function, however, the function must see b ==
> 6.

Ok, yes. So, you're talking about:

int foo (int x) { return b*x; }

I was on a slightly different wavelength.


> |>  int foo (int x) { return x; }
>
> |>  int main ()
> |>  {
> |>    int b = 5;
> |>    cout<<b<<endl<<foo(b++)<<endl;
> |>    cout<<b<<endl;
> |>  }
>
[snip].....

> The program is not legal C++, and the standard imposes no requirements
> as to what the compiler does with it.

Why is it not legal C++?


-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Thu, 3 Jul 2003 23:48:24 +0000 (UTC)
Raw View
""Dhruv"" <dhruvbird@gmx.net> wrote in message news:pan.2003.06.30.13.36.48.136928@gmx.net...

> > |>    cout<<b<<endl<<foo(b++)<<endl;

> [snip].....
>
> > The program is not legal C++, and the standard imposes no requirements
> > as to what the compiler does with it.
>
> Why is it not legal C++?

You modify b and use it for purposes other than that modification between sequence points.
You have to look at all the allowable orderings.   The compiler is perfectly free to evalutate
the first b and the b++ expression before calling any of the function calls.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Fri, 4 Jul 2003 06:27:12 +0000 (UTC)
Raw View
On Thu, 03 Jul 2003 23:48:24 +0000, Ron Natalie wrote:


> You modify b and use it for purposes other than that modification between sequence points.
> You have to look at all the allowable orderings.   The compiler is perfectly free to evalutate
> the first b and the b++ expression before calling any of the function calls.
>

Ok, so what you are saying is that the compiler may/may not evaluate b++
before putting b on the stream? Did I get that right?

Ok, which section/para in the steandard is all this input coming from. I
searched, but could only find: 5.2.2 which is function call. I was looking for
what James Kanze has quoted, about the side effects of the
expressions...... Where is it?


-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: comp.std.c++_2003-07-04@nmhq.net (Niklas Matthies)
Date: Fri, 4 Jul 2003 17:01:40 +0000 (UTC)
Raw View
On 2003-07-04 06:27, "Dhruv" <dhruvbird@gmx.net> wrote:
> On Thu, 03 Jul 2003 23:48:24 +0000, Ron Natalie wrote:
>
>> You modify b and use it for purposes other than that modification
>> between sequence points. You have to look at all the allowable
>> orderings.   The compiler is perfectly free to evalutate the first
>> b and the b++ expression before calling any of the function calls.
>
> Ok, so what you are saying is that the compiler may/may not evaluate b++
> before putting b on the stream? Did I get that right?

It's even worse: The compiler may emit code that results in the first
b being read while the second b is being written, resulting in either
reading a partially written b (yielding a more or less random value)
or even (under certain architectures) in a processor exception due to
concurrent load/store of the same memory location, hence crashing the
program. As far as the standard is concerned, it's simply undefined
behavior. Don't do it.

> Ok, which section/para in the steandard is all this input coming
> from. I searched, but could only find: 5.2.2 which is function call.
> I was looking for what James Kanze has quoted, about the side
> effects of the expressions...... Where is it?

Section 5, paragraph 4: "Between the previous and the next sequence
point a scalar object shall have its stored value modified at most
once by the evaluation of an expression. Furthermore, the prior value
shall be accessed only to determine the value to be stored."

-- Niklas Matthies

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Sun, 6 Jul 2003 19:10:23 +0000 (UTC)
Raw View
dhruvbird@gmx.net ("Dhruv") writes:

|>  On Sun, 29 Jun 2003 21:09:38 +0000, James Kanze wrote:

|>  [snip]......

|>  > Could you please indicate what makes you think this.  As far as
|>  > I can tell, the standard is clear.  A function call is a
|>  > sequence point, and the observable results of the program must
|>  > be as if all of the side effects of preceding functions have
|>  > taken place.

|>  The function foo is: int foo (int x) { return x; } It just returns
|>  the value passed, so there is no discrepency with regard to what
|>  was passed to foo().

You've snipped too much context.  Regardless of what the function is,
all side effects of evaluating its parameters must have taken place
before the function call.

|>  > |>  As in the function f() will get a parameter of 5, not 6.

|>  > The parameter is 5.  The parameter is the value of b before the
|>  > incrementation.  In the function, however, the function must see
|>  > b =3D=3D 6.

|>  Ok, yes. So, you're talking about:

|>  int foo (int x) { return b*x; }

I'm talking about any function, and the requirements the standard
places on the compiler.

|>  I was on a slightly different wavelength.

|>  > |>  int foo (int x) { return x; }

|>  > |>  int main ()
|>  > |>  {
|>  > |>    int b =3D 5;
|>  > |>    cout<<b<<endl<<foo(b++)<<endl;
|>  > |>    cout<<b<<endl;
|>  > |>  }

|>  [snip].....

|>  > The program is not legal C++, and the standard imposes no
|>  > requirements as to what the compiler does with it.

|>  Why is it not legal C++?

Because the standard says so. Chapter 5, paragraph 4:=20

    Except where noted, the oder of evaluation of operands of
    individual operators and subexpressions of individual expressions,
    and the order in which side effects take place, is unspecified.
    Between the previous and the next sequence point a scalar object
    shall have its stored value modified at most once by the
    evaluation of an expression.  Furthermore, the prior value shall
    be accessed only to determine the value to stored.  The
    requirements of this paragraph shall be met for each allowable
    ordering of the subexpressions of a full expression; otherwise,
    the behavior is undefined.

This is basically the same rule as in C.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Mon, 7 Jul 2003 01:14:06 +0000 (UTC)
Raw View
dhruvbird@gmx.net ("Dhruv") writes:

|>  On Thu, 03 Jul 2003 23:48:24 +0000, Ron Natalie wrote:

|>  > You modify b and use it for purposes other than that
|>  > modification between sequence points.  You have to look at all
|>  > the allowable orderings.  The compiler is perfectly free to
|>  > evalutate the first b and the b++ expression before calling any
|>  > of the function calls.

|>  Ok, so what you are saying is that the compiler may/may not
|>  evaluate b++ before putting b on the stream? Did I get that right?

No.  What he is saying is that your program is illegal.  But because
it involves undefined behavior, the compiler is not required to emit a
diagnostic -- in fact, there exist no requirements what so ever as to
what the compiler does.

|>  Ok, which section/para in the steandard is all this input coming
|>  from. I searched, but could only find: 5.2.2 which is function
|>  call. I was looking for what James Kanze has quoted, about the
|>  side effects of the expressions...... Where is it?

See my other posting.  Plus, of course, 1.9, which defines sequence
points and the required behavior of a program relative to them.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Mon, 7 Jul 2003 01:14:25 +0000 (UTC)
Raw View
dhruvbird@gmx.net ("Dhruv") writes:

|>  On Tue, 01 Jul 2003 23:44:45 +0000, James Kanze wrote:

|>  > |>  >Look at this code:

|>  > |>  >int foo (int x) { return x; }

|>  > |>  >int main ()
|>  > |>  >{
|>  > |>  >  int b =3D 5;
|>  > |>  >  cout<<b<<endl<<foo(b++)<<endl;
|>  > |>  >  cout<<b<<endl;
|>  > |>  >}

|>  > |>  >The output is something like:
|>  > |>  >6
|>  > |>  >5
|>  > |>  >6

|>  > |>  But you are passing by value, now declare foo as:

|>  > |>  int foo(int & x);

|>  > |>  and see what you get now.

|>  > He still gets undefined behavior.  Except that if foo takes a
|>  > non-const reference, the compiler is required to emit a
|>  > diagnostic, because the result of post-incrementation is not an
|>  > lvalue.

|>  > I'm not sure what point he is trying to make.  The standard
|>  > seems pretty clear to me with regards to the following points:

|>  >   - a function call is a sequence point, all side effects of
|>  >     previously evaluated expressions must take place before the
|>  >     function call, and

|>  >   - the results of a post-fix incrementation operator is the
|>  >     value of the operand before the incrementation.

|>  I agreed with you fully on what you have just said.

I don't think so.

|>  Even the example that I gave is proof that what you said is 100%
|>  correct.

No example can prove anything with regards to what I said, since
anything the compiler does is legal.  With luck, the code won't
compile, but it practice, it is extremely difficult for a compiler to
detect this particular error, and most don't.

|>  See the output: 6 5 6.=20

The output means nothing.  With another compiler, it could be 42 59
103.  Or the program core dumps.  Or it doesn't compile.

|>  That's cause streams a kinda backwards, so when the first thing
|>  (foo(b++)) is evaluated, foo gets 5, b becomes 6, then b is put on
|>  the stream, because of the reverse nature of streams, and you see
|>  b as 6, which it actually is. Intuituvely, you would expect b to
|>  be 5 here, but it's not.

I don't think you understand either what I am saying, nor really what
is going on.  What I am saying is that the code is illegal.  What is
happening is that the compiler is assuming that it doesn't have to
deal with such code, so is making no particular effort to get any
particular results.

|>  What point I'm trying to make has been lost (well, not actually).
|>  This post started out as a proposal to have ++(int) behave
|>  differently that what it does now, and it seems that if it is,
|>  then many of the things that people expect form post increment
|>  would be lost especially for function calls, where as you said,
|>  the expression should be evaluated before the function call.

Let's just say that changing that would break more than a few
programs.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: bop2@telia.com ("Bo Persson")
Date: Mon, 7 Jul 2003 19:00:57 +0000 (UTC)
Raw View
"James Kanze" <kanze@alex.gabi-soft.fr> wrote...
dhruvbird@gmx.net ("Dhruv") writes:


|>  What point I'm trying to make has been lost (well, not actually).
|>  This post started out as a proposal to have ++(int) behave
|>  differently that what it does now, and it seems that if it is,
|>  then many of the things that people expect form post increment
|>  would be lost especially for function calls, where as you said,
|>  the expression should be evaluated before the function call.

The problem here is that there are *several* function calls in the
full expression. The standars says that each function call will have
*its* parameters fully evaluated before the call. It doesn't say
whether other functions can or cannot have *their* parameters fully or
partially evaluated before or after (or both) any other function call.

The compiler will evaluate all the parameters in the best (like
"fastest") way it can find. This can mean that it computes all, some,
or partial, expressions before and/or between each function call. The
only restriction is that for each function, its parameters are fully
evaluated before the function is called. As a programmer, your only
promise is that you won't change the value of any subexpression the
compiler might already have evaluated.

In your case this subexpression is simply b, which is used twice. As
the value is not allowed to change within the expression (because it
is used more than once), the compiler is smart and loads it from
memory only once.


>Let's just say that changing that would break more than a few
>programs.

Understatement of the week. The suggestion is about 30 years too late.
:-)


Bo Persson
bop2@telia.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Fri, 27 Jun 2003 17:55:21 +0000 (UTC)
Raw View
dhruvbird@gmx.net (Dhruv) wrote in message
news:<cf18e89.0306230824.2fc5b07@posting.google.com>...
> A link to the article on comp.lang.c++ is:
> http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&safe=off&threadm=1056295930.713834%40radsrv1.tranzpeer.net&prev=/groups%3Fdq%3D%26num%3D25%26hl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dcomp.lang.c%252B%252B%26safe%3Doff%26start%3D25

> I've been thinking about op.++(int) (post inc/dec_rement), and it had
> occured to me that intuitively, it should POST INCREMENT the stuff,
> but instead it behaves like a normal function, so doing something is
> suicidal:

> int a,b;
> std::swap (a++, b++);

Is a compile time error, requiring a diagnostic.  If you ignore the
diagnostic, a good compiler will still not generate an object file.  If
the compiler does generate the object file, what happens in the code is
undefined by the standard.

> on the other hand, std::swap (++a, ++b); is fair enough.

Right.  Because pre-incrementation results in an lvalue.
Post-incrementation doesn't.

> I was wondering that if instead of evaluating the op.++(int) code, and
> then assigning the result to the lvalue, why not assign what ++ is to
> be applied to on to the lvalue, and then execute op.++() on the
> value. That would mean that no temporary is required, and ++(int) can
> be as efficiently as ++(void).

I don't quite understand what you are asking for.  The built-in version
of postfix operator ++ acts like a function for overloading purposes,
but it isn't a function.  The postfix operator ++ has a defined result.
It also has a defined side effect.  As with all operators with side
effects, the side effects are defined with regards to sequence points.
There is no "function" involved.

> Any ideas?????? I've heard that before standardization, post and pre
> inc/decrement were the same.

For non-class types, pre- and postfix incrementation and decrementation
are unchanged since the earliest days of C.  For user defined versions
of the operator, if memory serves me correctly (because this was long,
long before the standard), the user could only define a single ++ or --
operator for a given class type.  That operator was called indifferently
for postfix or for prefix; its results were the results of the
expression.  This meant, of course, that both prefix and postfix had the
same semantics -- totally unlike the built-in operator.  But I'm not
sure if this were ever really the case; at any rate, it was corrected to
the current situation before the first standard committee meeting took
place.

> How was it implemented that way??? (can anyone send a link, or an
> explanation)??????

    class Integer
    {
        int                 i ;
        Integer( int i ) : i( i ) {}
        Integer&            operator++()
        {
            ++ i ;
            return this ;
        }
    } ;

    ostream&
    operator<<( ostream& out, Integer const& i )
    {
        out << i.i ;
        return out ;
    }

    int
    main()
    {
        Integer i( 5 ) ;
        out << i ++ << '\n' ;
        return 0 ;
    }

In the distant past, this would display 5.  Today, it is illegal.

> Let me explain what I'm trying to say:

> assume:

> int a,b,c;

> <was>int foo(int& z) { int temp = z; return 2*temp; z = 1; }</was>
> <now is> int foo (int& z) { int temp = z; z = 1; return 2*temp; }
> </now is>
> <Thanks to Victor Bazarov for spotting the error>

> a = 1; b= 5;

> a = foo(b++);

Compiler error.  Should not compile.

> //a = 2*5 = 10.
> //b = 2; //surprise, but expected.

> This means that this is what happens:

> 1. The parameter to foo is reference to int, which is b, NOT the
> return value of op.++(int), so no need for temporary.

> 2. The code for op.++(int) is executed AFTER the full expression has
> evaluated, and after the temporaries (from any function call) have
> vanished.

A function call is a sequence point.  All side effects of evaluating its
parameters must take place before the function is called.  ALL.  The
code you show is not legal C++, but one can have similar effects with
global variables:

    int b ;
    int foo( int z ) { int r = b * z ; b = 1; return r ; }

    b = 5 ;
    int a = f( b ++ ) ;
    cout << a << ',' << b << '\n' ;

The last line is guaranteed by the standard to output 30, 1 -- the
incrementation of b in the parameter list must take place before the
function foo is called, so the first access to b in the function will
see 6.

> Would you settle for this instead of the current solution?

I haven't yet figured out what "this" is, so I couldn't say.  I would
like to see the order of evaluation somewhat more strictly defined, but
I'm not sure what you are proposing.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: qrczak@knm.org.pl ("Marcin 'Qrczak' Kowalczyk")
Date: Fri, 27 Jun 2003 17:55:47 +0000 (UTC)
Raw View
Dhruv wrote:

> 2. The code for op.++(int) is executed AFTER the full expression has
> evaluated, and after the temporaries (from any function call) have
> vanished.

This is crazy. The operation would no longer have a semantic of a function
call (I ignore sequence points and stuff, it doesn't matter on this level).
Instead it would influence what happens at some delicately chosen later
point of time, long after it finished execution.

You can't implement that in current C++ at all. No function can return
a result and say "and BTW, sometime later please also execute this".

I understand that you want to change the language, not implement it in
current C++; I only point out that this change would be far greater
than merely changing the meaning of a builtin operator. It changes what
"evaluate an expression" can mean.

Well, destroying temporaries already smells a bit like this, but at least it
happens externally to the individual operations, it results from there just
being function calls.

--
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Sat, 28 Jun 2003 07:21:28 +0000 (UTC)
Raw View
On Fri, 27 Jun 2003 17:55:21 +0000, kanz wrote:

>> Would you settle for this instead of the current solution?
>
> I haven't yet figured out what "this" is, so I couldn't say.  I would
> like to see the order of evaluation somewhat more strictly defined, but
> I'm not sure what you are proposing.
>
What I'm proposing is that instead of having operator++(int) being viewed
as a normal function, which executes code, and returns a value, and that
value is used as the result, why not have the object on which ++(int) is
applied be used as the result, and then when the expression has finished,
execute the code in operator++(int). That means that something like this:

c c::operator++(int) {
c temp = *this;
++(*this);
return temp;
}

NOTE: Temporary used here. If the construction cost of the class is high,
then ++(int) will be a very expensive operation.

Changes to:

void c::operator++(int) {
++(*this); }

This will preserve existing code too, and will make the newer code more
efficient. In usage, everything remains the same. Now, you cannot pass the
result of operator++(int) to a function that takes a reference, but if the
change is made, then you will be able to.

-Dhruv.







---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Sat, 28 Jun 2003 18:02:42 +0000 (UTC)
Raw View
On Fri, 27 Jun 2003 17:55:21 +0000, kanz wrote:

>
> A function call is a sequence point.  All side effects of evaluating its
> parameters must take place before the function is called.  ALL.  The
> code you show is not legal C++, but one can have similar effects with
> global variables:
>
>     int b ;
>     int foo( int z ) { int r = b * z ; b = 1; return r ; }
>
>     b = 5 ;
>     int a = f( b ++ ) ;
>     cout << a << ',' << b << '\n' ;
>
> The last line is guaranteed by the standard to output 30, 1 -- the
> incrementation of b in the parameter list must take place before the
> function foo is called, so the first access to b in the function will
> see 6.

How does it become 6? It remains 5, AFAIK. As in the function f() will get
a parameter of 5, not 6.

Look at this code:


int foo (int x) { return x; }

int main ()
{
  int b = 5;
  cout<<b<<endl<<foo(b++)<<endl;
  cout<<b<<endl;
}

The output is something like:
6
5
6

-Dhruv.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sun, 29 Jun 2003 08:06:58 +0000 (UTC)
Raw View
In article <pan.2003.06.28.05.03.50.766405@gmx.net>, Dhruv
<dhruvbird@gmx.net> writes
>How does it become 6? It remains 5, AFAIK. As in the function f() will get
>a parameter of 5, not 6.
>
>Look at this code:
>
>
>int foo (int x) { return x; }
>
>int main ()
>{
>  int b = 5;
>  cout<<b<<endl<<foo(b++)<<endl;
>  cout<<b<<endl;
>}
>
>The output is something like:
>6
>5
>6

But you are passing by value, now declare foo as:

int foo(int & x);

and see what you get now.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Sun, 29 Jun 2003 18:53:18 +0000 (UTC)
Raw View
On Sun, 29 Jun 2003 08:06:58 +0000, Francis Glassborow wrote:

> In article <pan.2003.06.28.05.03.50.766405@gmx.net>, Dhruv
> <dhruvbird@gmx.net> writes
>>How does it become 6? It remains 5, AFAIK. As in the function f() will get
>>a parameter of 5, not 6.
>>
>>Look at this code:
>>
>>
>>int foo (int x) { return x; }
>>
>>int main ()
>>{
>>  int b = 5;
>>  cout<<b<<endl<<foo(b++)<<endl;
>>  cout<<b<<endl;
>>}
>>
>>The output is something like:
>>6
>>5
>>6
>
> But you are passing by value, now declare foo as:
>
> int foo(int & x);
>
> and see what you get now.

That wouldn't compile. Because ++(int) returns a temporary, and you cannot
assign it to a reference.

Regards,
-Dhruv.







---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Sun, 29 Jun 2003 21:09:38 +0000 (UTC)
Raw View
dhruvbird@gmx.net ("Dhruv") writes:

|>  On Fri, 27 Jun 2003 17:55:21 +0000, kanz wrote:

|>  > A function call is a sequence point. All side effects of
|>  > evaluating its parameters must take place before the function is
|>  > called. ALL. The code you show is not legal C++, but one can
|>  > have similar effects with global variables:

|>  >     int b ;
|>  >     int foo( int z ) { int r =3D b * z ; b =3D 1; return r ; }

|>  >     b =3D 5 ;
|>  >     int a =3D f( b ++ ) ;
|>  >     cout << a << ',' << b << '\n' ;=20

|>  > The last line is guaranteed by the standard to output 30, 1 --
|>  > the incrementation of b in the parameter list must take place
|>  > before the function foo is called, so the first access to b in
|>  > the function will see 6.

|>  How does it become 6?

Because 5 + 1 is 6, and the incrementation is guaranteed to take place
before the function call.

|>  It remains 5, AFAIK.=20

Could you please indicate what makes you think this.  As far as I can
tell, the standard is clear.  A function call is a sequence point, and
the observable results of the program must be as if all of the side
effects of preceding functions have taken place.

|>  As in the function f() will get a parameter of 5, not 6.

The parameter is 5.  The parameter is the value of b before the
incrementation.  In the function, however, the function must see b =3D=3D
6.

|>  Look at this code:

|>  int foo (int x) { return x; }

|>  int main ()
|>  {
|>    int b =3D 5;
|>    cout<<b<<endl<<foo(b++)<<endl;
|>    cout<<b<<endl;
|>  }

|>  The output is something like:
|>  6
|>  5
|>  6

That's one possible output. Another is
    42
    65
    103
Still another is that the program doesn't output anything, but formats
your hard disk.

The program is not legal C++, and the standard imposes no requirements
as to what the compiler does with it.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: musiphil@bawi.org (KIM Seungbeom)
Date: Mon, 30 Jun 2003 04:32:49 +0000 (UTC)
Raw View
dhruvbird@gmx.net ("Dhruv") wrote in message news:<pan.2003.06.28.04.55.08.342090@gmx.net>...
>
> What I'm proposing is that instead of having operator++(int) being viewed
> as a normal function, which executes code, and returns a value, and that
> value is used as the result, why not have the object on which ++(int) is
> applied be used as the result, and then when the expression has finished,
> execute the code in operator++(int). That means that something like this:
>
> c c::operator++(int) {
> c temp = *this;
> ++(*this);
> return temp;
> }
>
> NOTE: Temporary used here. If the construction cost of the class is high,
> then ++(int) will be a very expensive operation.
>
> Changes to:
>
> void c::operator++(int) {
> ++(*this); }
>
> This will preserve existing code too, and will make the newer code more
> efficient. In usage, everything remains the same. Now, you cannot pass the
> result of operator++(int) to a function that takes a reference, but if the
> change is made, then you will be able to.

I agree with you on the whole.

http://groups.google.com/groups?selm=3DB89FB6.CDA02E84%40bawi.org
http://groups.google.com/groups?selm=3E35D682.5C2C35E3%40bawi.org

I think that almost always having to write two versions of increment
or decrement operators is clumsy, and that the performance penalty
on the postfix version is an undue one. Why should we care about the
temporary, even in the case the value of the whole expression
is discarded and thus ++i or i++ should not make a difference?

IMHO the problem is that currently operator++/-- is doing two things:
changing the value and returning a result. This is why the postfix
version should set up a temporary to store the value to return.
If we made them only specify how to change the value, postfix operators
would be liberated from the temporary and eventually prefix and postfix
operators could be integrated into one.

    void A::operator++() { /* increment A */ }

    A a;
    y = ++a;    // call a.operator++(), and use the value of a
    y = a++;    // use the value of a, and call a.operator++(),
                // possibly after the assignment

In this way, compilers are given more freedom to choose when to actually
increment the object, and there are no temporaries around, both of which
will lead to a better performance.

Anyway, I guess it's to late for such a big change. :-(

--
KIM seungbeom <musiphil@bawi.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: wmm@world.std.com ("William M. Miller")
Date: Tue, 1 Jul 2003 01:42:30 +0000 (UTC)
Raw View
<kanze@gabi-soft.fr> wrote in message
news:d6652001.0306240354.40874fe@posting.google.com...
> dhruvbird@gmx.net (Dhruv) wrote in message
> news:<cf18e89.0306230824.2fc5b07@posting.google.com>...
> > Any ideas?????? I've heard that before standardization, post and pre
> > inc/decrement were the same.
>
> For non-class types, pre- and postfix incrementation and decrementation
> are unchanged since the earliest days of C.  For user defined versions
> of the operator, if memory serves me correctly (because this was long,
> long before the standard), the user could only define a single ++ or --
> operator for a given class type.  That operator was called indifferently
> for postfix or for prefix; its results were the results of the
> expression.  This meant, of course, that both prefix and postfix had the
> same semantics -- totally unlike the built-in operator.  But I'm not
> sure if this were ever really the case; at any rate, it was corrected to
> the current situation before the first standard committee meeting took
> place.

That's almost right.  As I recall it, we were given a preprint
of the _unannotated_ reference manual (i.e., the ARM with the
commentary removed) and accepted that as the base document for
the Standard.  Between that time and the publication of the ARM,
the mechanism for distinguishing postfix operator++ and
operator-- was invented and incorporated into the first printing
of the ARM.  The first technical vote of the Committee was to
accept this change and apply it to the Working Paper.

-- William M. Miller


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Tue, 1 Jul 2003 23:44:45 +0000 (UTC)
Raw View
francis@robinton.demon.co.uk (Francis Glassborow) writes:

|>  In article <pan.2003.06.28.05.03.50.766405@gmx.net>, Dhruv
|>  <dhruvbird@gmx.net> writes
|>  >How does it become 6? It remains 5, AFAIK. As in the function f()
|>  >will get a parameter of 5, not 6.

|>  >Look at this code:

|>  >int foo (int x) { return x; }

|>  >int main ()
|>  >{
|>  >  int b =3D 5;
|>  >  cout<<b<<endl<<foo(b++)<<endl;
|>  >  cout<<b<<endl;
|>  >}

|>  >The output is something like:
|>  >6
|>  >5
|>  >6

|>  But you are passing by value, now declare foo as:

|>  int foo(int & x);

|>  and see what you get now.

He still gets undefined behavior.  Except that if foo takes a
non-const reference, the compiler is required to emit a diagnostic,
because the result of post-incrementation is not an lvalue.

I'm not sure what point he is trying to make.  The standard seems
pretty clear to me with regards to the following points:

  - a function call is a sequence point, all side effects of
    previously evaluated expressions must take place before the
    function call, and

  - the results of a post-fix incrementation operator is the value of
    the operand before the incrementation.

For the love of me, I can't figure out whether he disagrees with one
of these points (if so, I'd appreciate some quote from the standard,
because I've always firmly believed both), or if he hasn't understood
some part of it.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@alex.gabi-soft.fr (James Kanze)
Date: Tue, 1 Jul 2003 23:45:01 +0000 (UTC)
Raw View
dhruvbird@gmx.net ("Dhruv") writes:

|>  On Fri, 27 Jun 2003 17:55:21 +0000, kanz wrote:
|> =20
|>  >> Would you settle for this instead of the current solution?

|>  > I haven't yet figured out what "this" is, so I couldn't say.  I
|>  > would like to see the order of evaluation somewhat more strictly
|>  > defined, but I'm not sure what you are proposing.

|>  What I'm proposing is that instead of having operator++(int) being
|>  viewed as a normal function, which executes code, and returns a
|>  value, and that value is used as the result, why not have the
|>  object on which ++(int) is applied be used as the result, and then
|>  when the expression has finished, execute the code in
|>  operator++(int).

What do you mean exactly by "when the expression has finished"?  When
the i++ has finished, or when the complete expression has finished?
In the first case, you don't change anything with regards to existing
code; you still need the temporary (although perhaps the compiler
generates it automatically).  In the latter, you've changed the
semantics of existing legal code -- semantics on which I'm sure more
than one application depends.

--=20
James Kanze                                  mailto:kanze@gabi-soft.fr
Conseils en informatique orient=E9e objet/
                      Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France  Tel. +33 1 41 89 80 93

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net (Dhruv)
Date: Tue, 24 Jun 2003 01:49:36 +0000 (UTC)
Raw View
A link to the article on comp.lang.c++ is:
http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&safe=off&threadm=1056295930.713834%40radsrv1.tranzpeer.net&prev=/groups%3Fdq%3D%26num%3D25%26hl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dcomp.lang.c%252B%252B%26safe%3Doff%26start%3D25


I've been thinking about op.++(int) (post inc/dec_rement), and it had
occured to me that intuitively, it should POST INCREMENT the stuff,
but instead it behaves like a normal function, so doing something is
suicidal:

int a,b;
std::swap (a++, b++);

on the other hand, std::swap (++a, ++b); is fair enough.

I was wondering that if instead of evaluating the op.++(int) code, and
then assigning the result to the lvalue, why not assign what ++ is to
be applied to on to the lvalue, and then execute op.++() on the
value. That would mean that no temporary is required, and ++(int) can
be as efficiently as ++(void). Any ideas?????? I've heard that before
standardization, post and pre inc/dec_rement were the same. How was it
implemented that way??? (can anyone send a link, or an
explanation)??????

Let me explain what I'm trying to say:

assume:

int a,b,c;

<was>int foo(int& z) { int temp = z; return 2*temp; z = 1; }</was>
<now is> int foo (int& z) { int temp = z; z = 1; return 2*temp; }
</now is>
<Thanks to Victor Bazarov for spotting the error>

a = 1; b= 5;

a = foo(b++);
//a = 2*5 = 10.
//b = 2; //surprise, but expected.

This means that this is what happens:

1. The parameter to foo is reference to int, which is b, NOT the
return value of op.++(int), so no need for temporary.

2. The code for op.++(int) is executed AFTER the full expression has
evaluated, and after the temporaries (from any function call) have
vanished.

Would you settle for this instead of the current solution?

Regards,
-Dhruv.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]