Pitfall of proxy instead of temporary?

Discussion in 'C++' started by Frederick Gotham, Aug 30, 2006.

  1. 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.
     
    Frederick Gotham, Aug 30, 2006
    #1
    1. Advertisements

  2. That way is probably used for very special cases only. Any example?
     
    Roland Pibinger, Aug 30, 2006
    #2
    1. Advertisements

  3. Frederick Gotham

    Old Wolf Guest

    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.
     
    Old Wolf, Aug 31, 2006
    #3
  4. 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...)
     
    Frederick Gotham, Aug 31, 2006
    #4
  5. Frederick Gotham

    Kai-Uwe Bux Guest

    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
     
    Kai-Uwe Bux, Aug 31, 2006
    #5
  6. 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;

    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.
     
    Frederick Gotham, Aug 31, 2006
    #6
  7. Frederick Gotham

    Kai-Uwe Bux Guest

    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.

    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.

    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Aug 31, 2006
    #7
  8. Kai-Uwe Bux posted:

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


    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++.
     
    Frederick Gotham, Aug 31, 2006
    #8
  9. Frederick Gotham

    Pete Becker Guest

    Iterators are required to be copy constructible.
     
    Pete Becker, Aug 31, 2006
    #9
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.