Pitfall of proxy instead of temporary?

F

Frederick Gotham

There are two common ways of implementing the postincrement operator:

(1) Copy-construct a temporary.
Increment the original.
Return the tempory.

(2) Create an "proxy" object which, upon its destruction, will increment
the original object.
Return the original object.

It appears to me that method (2) might act strangely in the following
circumstance:

x = x++, x++, x;

There's a sequence point between the comma operands, but any temporaries
aren't destroyed until the semi-colon is reached.
 
R

Roland Pibinger

There are two common ways of implementing the postincrement operator:
(2) Create an "proxy" object which, upon its destruction, will increment
the original object. Return the original object.

That way is probably used for very special cases only. Any example?
 
O

Old Wolf

Frederick said:
There are two common ways of implementing the postincrement operator:

(1) Copy-construct a temporary.
Increment the original.
Return the tempory.

(2) Create an "proxy" object which, upon its destruction, will increment
the original object.
Return the original object.

It appears to me that method (2) might act strangely in the following
circumstance:

x = x++, x++, x;

There's a sequence point between the comma operands, but any temporaries
aren't destroyed until the semi-colon is reached.

If by 2 you mean something like:
X X::eek:perator++(int)
{
Proxy p(*this);
return *this;
}

then there is no problem, because 'p' is destroyed before the
sequence point associated with the function returning.
 
F

Frederick Gotham

Old Wolf posted:
If by 2 you mean something like:
X X::eek:perator++(int)
{
Proxy p(*this);
return *this;
}

then there is no problem, because 'p' is destroyed before the
sequence point associated with the function returning.


The object, "p", is destroyed before the object is returned by reference, so
the function would act like a preincrement rather than a postincrement.

(I can't remember exactly how the proxy thing actually worked...)
 
K

Kai-Uwe Bux

Frederick said:
Old Wolf posted:



The object, "p", is destroyed before the object is returned by reference,
so the function would act like a preincrement rather than a postincrement.

(I can't remember exactly how the proxy thing actually worked...)

Maybe, you recall something like this:

struct post_inc {

struct post_inc_proxy {

post_inc & i;

post_inc_proxy ( post_inc & r )
: i ( r )
{}

~post_inc_proxy ( void ) {
++i.i;
}

operator post_inc const & ( void ) {
return i;
}

}; // post_inc_proxy;

int i;

post_inc ( int v )
: i ( v )
{}

post_inc_proxy operator++ ( int ) {
return ( *this );
}

}; // post_inc


#include <iostream>

int main ( void ) {
{
post_inc a ( 5 );
post_inc b ( 20 );
post_inc c ( 20 );
b = a++, c = a++, a++;
std::cout << a.i
<< '\n'
<< b.i
<< '\n'
<< c.i
<< '\n';
}
{
int a ( 5 );
int b ( 20 );
int c ( 20 );
b = a++, c = a++, a++;
std::cout << a
<< '\n'
<< b
<< '\n'
<< c
<< '\n';
}
}

And, yes: it fails with the comma operator.


Best

Kai-Uwe Bux
 
F

Frederick Gotham

Kai-Uwe Bux posted:
And, yes: it fails with the comma operator.


To be honest, I wouldn't even bother defining a postincrement operator for
my class -- it's too messy. If they really want to write:

x = obj++;

, then let them write:

x = obj;
++obj;

On a semi-unrelated topic:
Is an implementation of C++ allowed to change the following:

for(T i = 0; i != MAX; i++)

into:

for(T i = 0; i != MAX; ++i)

That is to say, is it allowed to change a postincrement to a preincrement
_if_ the result is discarded. There's still a lot of programmers out there
who use i++ where ++i would suffice.
 
K

Kai-Uwe Bux

Frederick said:
Kai-Uwe Bux posted:



To be honest, I wouldn't even bother defining a postincrement operator for
my class -- it's too messy. If they really want to write:

x = obj++;

, then let them write:

x = obj;
++obj;

The standard idiom

T operator++ ( int ) {
T dummy ( *this );
++ (*this);
return ( dummy );
}

is not messy at all. Using return value optimization and inlinening it
should compile to virtually the same object code.

On a semi-unrelated topic:
Is an implementation of C++ allowed to change the following:

for(T i = 0; i != MAX; i++)

into:

for(T i = 0; i != MAX; ++i)

That is to say, is it allowed to change a postincrement to a preincrement
_if_ the result is discarded.

That depends on the type T. If the observable behavior is the same, then:
yes, the implementation is allowed to make the change. However, for
user-defined types, the compiler would have to prove that the effect of
postfix++ and prefix++ on objects of type T is the same: I do not know of a
provision in the standard that in a well-formed program postfix and prefix
operators have semantics that are related in the usual way.
There's still a lot of programmers out there who use i++ where ++i would
suffice.


Best

Kai-Uwe Bux
 
F

Frederick Gotham

Kai-Uwe Bux posted:
The standard idiom

T operator++ ( int ) {
T dummy ( *this );
++ (*this);
return ( dummy );
}

is not messy at all. Using return value optimization and inlinening it
should compile to virtually the same object code.


But then there's the small issue of an accessible copy-constructor...

That depends on the type T. If the observable behavior is the same, then:
yes, the implementation is allowed to make the change. However, for
user-defined types, the compiler would have to prove that the effect of
postfix++ and prefix++ on objects of type T is the same: I do not know of a
provision in the standard that in a well-formed program postfix and prefix
operators have semantics that are related in the usual way.


Maybe it would be a good idea to allow postincrement to become preincrement
when the value is discarded? Or then again, maybe we should just drill into
people's head that they should be using ++i instead of i++.
 
P

Pete Becker

Frederick said:
Kai-Uwe Bux posted:





But then there's the small issue of an accessible copy-constructor...

Iterators are required to be copy constructible.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top