Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > post and pre-increment operator overloading not behaving like

Reply
Thread Tools

post and pre-increment operator overloading not behaving like

 
 
simudream@gmail.com
Guest
Posts: n/a
 
      11-21-2007
//hi maybe helpful others can look at this code and
//tell me why the class code won't behave like
//intrinsic types with post and pre increment

//Version: 1.00

#include <iostream>
using std::cout;
using std::endl;
using std:stream;

class IntWrapper
{
friend ostream & operator<<( ostream&, const IntWrapper& );

public:
IntWrapper( int val = 0 ) : i(val) {;}

IntWrapper operator+( const IntWrapper& rhs) const
{
//use RVO
return IntWrapper( this->i + rhs.i );
}

IntWrapper& operator++()
{
++this->i;
return *this;
}

IntWrapper operator++(int)
{
IntWrapper tmp(*this);
this->operator++();
return tmp;
}

private:
int i;

};

ostream &operator<<( ostream &, const IntWrapper & );

int main()
{
//interesting results of the post and pre increment operators

IntWrapper test;
int i = 0;

IntWrapper test1 = test + test++;
int test2 = i + i++;

//test1 should be the same as test2 but they are not

cout << test1 << " <- This should be the same as this one -> " <<
test2 << endl;

cout << i << i++ << test << test++ << endl;

system("pause");
}

ostream &operator<<( ostream &output, const IntWrapper &r )
{
output << r.i;
return output;
}
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      11-21-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> //hi maybe helpful others can look at this code and
> //tell me why the class code won't behave like
> //intrinsic types with post and pre increment

[snip]
> IntWrapper test1 = test + test++;
> int test2 = i + i++;
>
> //test1 should be the same as test2 but they are not


As far as I can see you have unspecified behavior according to clause [5/4]
of the standard. Your assumption that both lines should behave the same is
not waranted by the standard.


Best

Kai-Uwe Bux
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      11-21-2007
On Nov 21, 6:52 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > //hi maybe helpful others can look at this code and
> > //tell me why the class code won't behave like
> > //intrinsic types with post and pre increment

> [snip]
> > IntWrapper test1 = test + test++;
> > int test2 = i + i++;


> > //test1 should be the same as test2 but they are not


> As far as I can see you have unspecified behavior according to
> clause [5/4] of the standard.


Not unspecified. Undefined. At least in the second line. (The
first is unspecified.)

> Your assumption that both lines should behave the same is not
> waranted by the standard.


The assumption that his program doesn't reformat his hard disk
is not warranted by the standard.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      11-21-2007
James Kanze wrote:

> On Nov 21, 6:52 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
>> (E-Mail Removed) wrote:
>> > //hi maybe helpful others can look at this code and
>> > //tell me why the class code won't behave like
>> > //intrinsic types with post and pre increment

>> [snip]
>> > IntWrapper test1 = test + test++;
>> > int test2 = i + i++;

>
>> > //test1 should be the same as test2 but they are not

>
>> As far as I can see you have unspecified behavior according to
>> clause [5/4] of the standard.

>
> Not unspecified. Undefined. At least in the second line.


Well, I don't see a variable that has its value modified twice between
sequence points. So it must be the condition

"Furthermore, the prior value shall be accessed only to determine the
value to be stored."

and I have to admit that I never have been able to figure out the meaning of
this sentence.

> (The first is unspecified.)


Yup.

[snip]


Best

Kai-Uwe Bux
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-21-2007
* Kai-Uwe Bux:
> James Kanze wrote:
>
>> On Nov 21, 6:52 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
>>> (E-Mail Removed) wrote:
>>>> //hi maybe helpful others can look at this code and
>>>> //tell me why the class code won't behave like
>>>> //intrinsic types with post and pre increment
>>> [snip]
>>>> IntWrapper test1 = test + test++;
>>>> int test2 = i + i++;
>>>> //test1 should be the same as test2 but they are not
>>> As far as I can see you have unspecified behavior according to
>>> clause [5/4] of the standard.

>> Not unspecified. Undefined. At least in the second line.

>
> Well, I don't see a variable that has its value modified twice between
> sequence points. So it must be the condition
>
> "Furthermore, the prior value shall be accessed only to determine the
> value to be stored."
>
> and I have to admit that I never have been able to figure out the meaning of
> this sentence.


It's probably intended to mean that if an epression modifies a variable,
the expression shall not use the prior value of the variable for
anything else than the computation of the new value, e.g. not displayed
or stored elsewhere. That way the compiler can optimize prematurely to
its heart content without ensuring that the value is consistent during
the evaluation of the expression. But as the incorrect examples in the
standard demonstrate, this part of the standard is bungled, and one must
therefore ignore it & apply common sense instead of the literal wording.

Common sense is to not use side effects in sub-expressions.

Cheers, & hth.

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Andre Kostur
Guest
Posts: n/a
 
      11-21-2007
(E-Mail Removed) wrote in news:d49de4fe-d494-4f62-b5cf-
(E-Mail Removed):

> //hi maybe helpful others can look at this code and
> //tell me why the class code won't behave like
> //intrinsic types with post and pre increment
>
> //Version: 1.00
>

[snip code which, IMHO, is correct]

> int main()
> {
> //interesting results of the post and pre increment operators
>
> IntWrapper test;
> int i = 0;
>
> IntWrapper test1 = test + test++;


Undefined Behaviour. Reading and modifying a value without an
intervening sequence point.

> int test2 = i + i++;


Undefined Behaviour. Reading and modifying a value without an
intervening sequence point. And apparently the Undefined Behaviour is
different between basic types and user defined classes.

>
> //test1 should be the same as test2 but they are not
>
> cout << test1 << " <- This should be the same as this one -> " <<
> test2 << endl;
>
> cout << i << i++ << test << test++ << endl;
>
> system("pause");
> }

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      11-22-2007
On Nov 21, 1:44 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> James Kanze wrote:
> > On Nov 21, 6:52 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> >> (E-Mail Removed) wrote:
> >> > //hi maybe helpful others can look at this code and
> >> > //tell me why the class code won't behave like
> >> > //intrinsic types with post and pre increment
> >> [snip]
> >> > IntWrapper test1 = test + test++;
> >> > int test2 = i + i++;


> >> > //test1 should be the same as test2 but they are not


> >> As far as I can see you have unspecified behavior according to
> >> clause [5/4] of the standard.


> > Not unspecified. Undefined. At least in the second line.


> Well, I don't see a variable that has its value modified twice
> between sequence points. So it must be the condition


> "Furthermore, the prior value shall be accessed only to
> determine the value to be stored."


> and I have to admit that I never have been able to figure out
> the meaning of this sentence.


It could be clearer, but what it basically means is that if you
modify the variable, the only legal accesses without an
intervening sequence point are those which are used to determine
the new value. Intuitively, if there is no sequence point, then
cause and effect ordering may still render the code legal: in an
expression like "a = a + 1", there may not be a sequence point
between the two accesses to a, but it's quite clear that the
read must be occur before the write, since we can't know what to
write until the read has occured.

In some ways, the rule is very much like the rule for accessing
in a multithreaded environment: if any access is a modification,
then all accesses must be "protected". Here, the protection may
be provided by an intervening sequence point, or by a strict
value dependency.

IMHO, the word "prior" in the quoted sentence only causes
confusion. In an expression such as "i + i++", does the first i
access the "prior" value, or some later value. In fact, the
standard states elsewhere that there is undefined behavior is
any legal ordering would result in undefined behavior. Since
the ordering which evaluates the left hand side of the +
operator first does access the "prior" value, the expression has
undefined behavior. But as there are no cases without an
intervening sequence point which don't allow such reordering,
the "prior" is really not needed.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      11-22-2007
On Nov 21, 2:18 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * Kai-Uwe Bux:
> > James Kanze wrote:
> >> On Nov 21, 6:52 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> >>> (E-Mail Removed) wrote:
> >>>> //hi maybe helpful others can look at this code and
> >>>> //tell me why the class code won't behave like
> >>>> //intrinsic types with post and pre increment
> >>> [snip]
> >>>> IntWrapper test1 = test + test++;
> >>>> int test2 = i + i++;
> >>>> //test1 should be the same as test2 but they are not
> >>> As far as I can see you have unspecified behavior according to
> >>> clause [5/4] of the standard.
> >> Not unspecified. Undefined. At least in the second line.


> > Well, I don't see a variable that has its value modified
> > twice between sequence points. So it must be the condition


> > "Furthermore, the prior value shall be accessed only to
> > determine the value to be stored."


> > and I have to admit that I never have been able to figure
> > out the meaning of this sentence.


> It's probably intended to mean that if an epression modifies a
> variable, the expression shall not use the prior value of the
> variable for anything else than the computation of the new
> value, e.g. not displayed or stored elsewhere.


The prior value may not be accessed, period, other than to
determine the new value. You don't have to display or store it
elsewhere---you just have to use it in an expression. (Of
course, I'm not sure that means anything in practice. But it's
what the standard says.)

> That way the compiler can optimize prematurely to its heart
> content without ensuring that the value is consistent during
> the evaluation of the expression. But as the incorrect
> examples in the standard demonstrate,


Which "incorrect examples"? The only incorrection I see in the
examples is the use of the word "unspecified" rather than
"undefined" in the comments. The preceding (normative) text
makes it quite clear, however, that the behavior in the examples
is undefined. (There are other cases where it isn't so clear,
of course.)

> this part of the standard is bungled, and one must therefore
> ignore it & apply common sense instead of the literal wording.


That's your opinion, and it isn't shared by the experts (unless
you mean something different by "bungled" than I understand).

Generally speaking, it is recognized that the model used to
express the constraints here is not ideal. The C committee
discussed the issues when updating the C standard (resulting in
C99). The consensus among the experts at the time was that
while not the best, the current wording was sufficient for what
was wanted, and that a rewrite wasn't necessary. (The rules
here are taken verbatim from the C standard.)

Of course, the rules don't address threading issues. Since the
C++ standard is addressing threading, this section does require
rework, and is the subject of a complete rewrite. In
collaboration with the C committee---the intent is that whatever
we rewrite will be acceptable to them, and integrated into the
next version of the C standard as well.

> Common sense is to not use side effects in sub-expressions.


Ideally: each statement does one thing, and one thing only. A
flow control statement doesn't modify program state, and a
statement which modifies an object doesn't modify any other
program state, nor affect flow control.

Practically, there are exceptions. But they should be very
rare (and almost always concern modifying state in a flow
control statement, and not modifying two different objects in a
single statement).

Hopefully, we've gotten past the days when people thought that
things like:
while ( *p ++ = *q ++ ) ;
was acceptable in production code.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-22-2007
* James Kanze:
> On Nov 21, 2:18 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
>> * Kai-Uwe Bux:
>>> James Kanze wrote:
>>>> On Nov 21, 6:52 am, Kai-Uwe Bux <(E-Mail Removed)> wrote:
>>>>> (E-Mail Removed) wrote:
>>>>>> //hi maybe helpful others can look at this code and
>>>>>> //tell me why the class code won't behave like
>>>>>> //intrinsic types with post and pre increment
>>>>> [snip]
>>>>>> IntWrapper test1 = test + test++;
>>>>>> int test2 = i + i++;
>>>>>> //test1 should be the same as test2 but they are not
>>>>> As far as I can see you have unspecified behavior according to
>>>>> clause [5/4] of the standard.
>>>> Not unspecified. Undefined. At least in the second line.

>
>>> Well, I don't see a variable that has its value modified
>>> twice between sequence points. So it must be the condition

>
>>> "Furthermore, the prior value shall be accessed only to
>>> determine the value to be stored."

>
>>> and I have to admit that I never have been able to figure
>>> out the meaning of this sentence.

>
>> It's probably intended to mean that if an epression modifies a
>> variable, the expression shall not use the prior value of the
>> variable for anything else than the computation of the new
>> value, e.g. not displayed or stored elsewhere.

>
> The prior value may not be accessed, period, other than to
> determine the new value. You don't have to display or store it
> elsewhere---you just have to use it in an expression. (Of
> course, I'm not sure that means anything in practice. But it's
> what the standard says.)


Exactly how do you think that's different from what I wrote?


>> That way the compiler can optimize prematurely to its heart
>> content without ensuring that the value is consistent during
>> the evaluation of the expression. But as the incorrect
>> examples in the standard demonstrate,

>
> Which "incorrect examples"? The only incorrection I see in the
> examples is the use of the word "unspecified" rather than
> "undefined" in the comments. The preceding (normative) text
> makes it quite clear, however, that the behavior in the examples
> is undefined. (There are other cases where it isn't so clear,
> of course.)


Again, how is that different from what I wrote?


>> this part of the standard is bungled, and one must therefore
>> ignore it & apply common sense instead of the literal wording.

>
> That's your opinion, and it isn't shared by the experts (unless
> you mean something different by "bungled" than I understand).


It's being corrected in C++0x.

And I remind you that you have participated in extended discussions in
e.g. comp.std.c++ about what the wording means, where you have taken on
minority positions.

Your reference to unspecified "experts" is therefore (a) evidently
incorrect, and (b) fallacious anyway.


> Generally speaking, it is recognized that the model used to
> express the constraints here is not ideal. The C committee
> discussed the issues when updating the C standard (resulting in
> C99). The consensus among the experts at the time was that
> while not the best, the current wording was sufficient for what
> was wanted, and that a rewrite wasn't necessary. (The rules
> here are taken verbatim from the C standard.)
>
> Of course, the rules don't address threading issues. Since the
> C++ standard is addressing threading, this section does require
> rework, and is the subject of a complete rewrite. In
> collaboration with the C committee---the intent is that whatever
> we rewrite will be acceptable to them, and integrated into the
> next version of the C standard as well.


You may of course, by association, include yourself in the panel of
people rewriting this stuff, if you're participating in the committee
(do you, still?), and you may attribute the changes to anything vaguely
associated. Let the associations run wild.


>> Common sense is to not use side effects in sub-expressions.

>
> Ideally: each statement does one thing, and one thing only. A
> flow control statement doesn't modify program state, and a
> statement which modifies an object doesn't modify any other
> program state, nor affect flow control.
>
> Practically, there are exceptions. But they should be very
> rare (and almost always concern modifying state in a flow
> control statement, and not modifying two different objects in a
> single statement).
>
> Hopefully, we've gotten past the days when people thought that
> things like:
> while ( *p ++ = *q ++ ) ;
> was acceptable in production code.


It's an idiom, presented in the first version of "The C Programming
Language" by Kernighan & Ritchie.

Cheers, & hth.,

- Alf


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
overloading operator->*() and operator->() gob00st@googlemail.com C++ 2 02-21-2009 04:26 AM
overloading operator->*() and operator->() gob00st@googlemail.com C++ 11 02-20-2009 08:52 PM
user defined conversion operator or operator overloading? hurcan solter C++ 3 08-29-2007 07:39 PM
Why is overloading operator. (member operator) forbidden? dascandy@gmail.com C++ 11 05-16-2007 07:54 PM
Operator overloading on "default" operator John Smith C++ 2 10-06-2004 10:22 AM



Advertisments