boost::scoped_ptr rationale?

Discussion in 'C++' started by Juha Nieminen, Jul 19, 2010.

  1. Can someone give me an example where it makes any sense to use
    boost::scoped_ptr?

    I mean: As opposed to instantiating the object locally (ie. on the
    stack). A stack-allocated object not only achieves the same automatic
    lifetime, but it's also much more efficient (allocating an object on
    the stack can be tens of times faster than allocating it with 'new').
     
    Juha Nieminen, Jul 19, 2010
    #1
    1. Advertising

  2. Juha Nieminen wrote:
    > Can someone give me an example where it makes any sense to use
    > boost::scoped_ptr?
    >
    > I mean: As opposed to instantiating the object locally (ie. on the
    > stack). A stack-allocated object not only achieves the same automatic
    > lifetime, but it's also much more efficient (allocating an object on
    > the stack can be tens of times faster than allocating it with 'new').


    Did you ever succeed to instantiate a polymorphic object on the stack?
    Probably not. The exact type must be known at compile time for this
    purpose. So, no factory pattern.

    Did you ever need to deal with different instances and controlled
    lifetime? The lifetime of stack objects is restricted to {} blocks. At
    least they cannot interdigitate.

    scoped_ptr is one of the easiest ways to provide exception safety for
    local dynamic objects.


    Marcel
     
    Marcel Müller, Jul 19, 2010
    #2
    1. Advertising

  3. Juha Nieminen

    Öö Tiib Guest

    On 19 juuli, 18:10, Juha Nieminen <> wrote:
    >   Can someone give me an example where it makes any sense to use
    > boost::scoped_ptr?


    There is nothing better for a polymorphic component of object.
    boost::scoped_ptr data member automatically disables default
    assignment and copy construction unlike std::auto_ptr.

    >   I mean: As opposed to instantiating the object locally (ie. on the
    > stack). A stack-allocated object not only achieves the same automatic
    > lifetime, but it's also much more efficient (allocating an object on
    > the stack can be tens of times faster than allocating it with 'new').


    I have used it less often for function local objects. Leigh and Marcel
    gave most of the good reasons. Additionally there exist objects that
    protect themselves against being allocated statically or automatically
    (some techniques give undefined results with objects of static or
    automatic storage). If you need local temporary instance of such then
    boost::scoped_ptr is better than raw pointer.
     
    Öö Tiib, Jul 19, 2010
    #3
  4. Juha Nieminen

    James Kanze Guest

    On Jul 19, 4:10 pm, Juha Nieminen <> wrote:
    > Can someone give me an example where it makes any sense to use
    > boost::scoped_ptr?


    > I mean: As opposed to instantiating the object locally (ie. on
    > the stack). A stack-allocated object not only achieves the
    > same automatic lifetime, but it's also much more efficient
    > (allocating an object on the stack can be tens of times faster
    > than allocating it with 'new').


    class B { public : virual ~B() {} ... };
    class D1 : public B { ... };
    class D2 : public B { ... };

    void f(bool condition)
    {
    boost::scoped_ptr<B> p(condition ? new D1 : new D2);
    ...
    }

    It can also be useful as a member of a class.

    --
    James Kanze
     
    James Kanze, Jul 19, 2010
    #4
  5. James Kanze <>, on 19/07/2010 10:34:58, wrote:

    > On Jul 19, 4:10 pm, Juha Nieminen<> wrote:
    >> Can someone give me an example where it makes any sense to use
    >> boost::scoped_ptr?

    >
    >> I mean: As opposed to instantiating the object locally (ie. on
    >> the stack). A stack-allocated object not only achieves the
    >> same automatic lifetime, but it's also much more efficient
    >> (allocating an object on the stack can be tens of times faster
    >> than allocating it with 'new').

    >
    > class B { public : virual ~B() {} ... };
    > class D1 : public B { ... };
    > class D2 : public B { ... };
    >
    > void f(bool condition)
    > {
    > boost::scoped_ptr<B> p(condition ? new D1 : new D2);
    > ...
    > }


    I don't know if it's expected or not, but MinGW 4.4.0 rejects the above
    with the following error:

    "conditional expression between distinct pointer types 'D1*' and 'D2*'
    lacks a cast"

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Jul 19, 2010
    #5
  6. Juha Nieminen

    Balog Pal Guest

    "Francesco S. Carta" <>
    >> void f(bool condition)
    >> {
    >> boost::scoped_ptr<B> p(condition ? new D1 : new D2);
    >> ...
    >> }

    >
    > I don't know if it's expected or not, but MinGW 4.4.0 rejects the above
    > with the following error:
    >
    > "conditional expression between distinct pointer types 'D1*' and 'D2*'
    > lacks a cast"


    The error message is correct and good: the ?: expression has a single type.
    If the types of the two parts differ, it tries to convert B to a and A to B,
    expecting exactly one of them succeeding.

    In the above case a cast to B* (or another subclass of B that is common for
    D1 and D2 ) shall be there on one side.
     
    Balog Pal, Jul 19, 2010
    #6
  7. Balog Pal <>, on 19/07/2010 20:30:16, wrote:

    > "Francesco S. Carta" <>
    >>> void f(bool condition)
    >>> {
    >>> boost::scoped_ptr<B> p(condition ? new D1 : new D2);
    >>> ...
    >>> }

    >>
    >> I don't know if it's expected or not, but MinGW 4.4.0 rejects the
    >> above with the following error:
    >>
    >> "conditional expression between distinct pointer types 'D1*' and 'D2*'
    >> lacks a cast"

    >
    > The error message is correct and good: the ?: expression has a single
    > type. If the types of the two parts differ, it tries to convert B to a
    > and A to B, expecting exactly one of them succeeding.
    >
    > In the above case a cast to B* (or another subclass of B that is common
    > for D1 and D2 ) shall be there on one side.


    Ah, thank you very much for the explanation, I never incurred in such an
    error... I must have missed to set to mind that the ternary conditional
    operator must resolve to exactly one type - assuming I ever read about
    it ;-)

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Jul 19, 2010
    #7
  8. Leigh Johnston posted this message in ROT13 encoding:

    > "Juha Nieminen" <> wrote in message
    > news:4c446afd$0$4114$...
    >> Can someone give me an example where it makes any sense to use
    >> boost::scoped_ptr?

    >
    > If the stack is too small for the object and yet you still want stack object
    > semantics (including RAII/exception support).


    You can always increase stack size. I came across a program that demanded
    32 Mb of stack.

    >> I mean: As opposed to instantiating the object locally (ie. on the
    >> stack). A stack-allocated object not only achieves the same automatic
    >> lifetime, but it's also much more efficient (allocating an object on
    >> the stack can be tens of times faster than allocating it with 'new').

    >
    > Indeed.


    Actually, that's not really true. Try writing some code to time the
    differences as a function of space allocated, sometime. It's closer than
    you'd think -- it sure surprised me. Here's a note from the code:

    Now, this speed-up is actually quite minimal -- using the heap and
    malloc() is a little faster, depending on the operating system and the
    amount of thread data being allocated. Not until the amount of thread
    data exceeds 1 Mb does the stack implementation become significantly
    faster.

    This experiment came about because I implemented as stack-based thread
    handler based on someone else's implemenation, because he said it was
    faster. I posted that on a newsgroup, and someone said I was wrong.
    And sure enough, I was, to some extent.

    --
    Authentic:
    Indubitably true, in somebody's opinion.
     
    Chris Ahlstrom, Jul 19, 2010
    #8
  9. Leigh Johnston <> wrote:
    > If the stack is too small for the object and yet you still want stack object
    > semantics (including RAII/exception support).


    That may indeed be one situation. I have had situations (in small test
    programs) where trying to eg. use a stack-allocated array which was too
    large made the program fail.
     
    Juha Nieminen, Jul 20, 2010
    #9
  10. Marcel Müller <> wrote:
    > Did you ever succeed to instantiate a polymorphic object on the stack?
    > Probably not. The exact type must be known at compile time for this
    > purpose. So, no factory pattern.


    If you don't know the actual type of the object at compile time in
    the current scope, but nevertheless want to use scoped_ptr to handle
    it, it would mean that there has to be some function which you call from
    the current scope and which returns a raw pointer to the object it
    allocated (leaving the responsibility of deleting the object up to the
    calling code). While this is certainly something you can do, I would say
    it's a pretty bad design (allocating something and then leaving the
    deletion up to the calling code is asking for trouble in a non-garbage-
    collected environment).

    If I understood correctly, that "factory" function can certainly not
    return a scoped_ptr (because it's non-copyable).

    Of course it could take a scoped_ptr reference as parameter and put
    the allocated object there. Feels a bit contrived, though.

    > The lifetime of stack objects is restricted to {} blocks.


    So is the lifetime of an object handled by scoped_ptr (the object cannot
    be shared nor transferred to anything else). So?

    > scoped_ptr is one of the easiest ways to provide exception safety for
    > local dynamic objects.


    I didn't doubt that. My question is why you would allocate the object
    dynamically in the first place.
     
    Juha Nieminen, Jul 20, 2010
    #10
  11. Öö Tiib <> wrote:
    > On 19 juuli, 18:10, Juha Nieminen <> wrote:
    >>   Can someone give me an example where it makes any sense to use
    >> boost::scoped_ptr?

    >
    > There is nothing better for a polymorphic component of object.
    > boost::scoped_ptr data member automatically disables default
    > assignment and copy construction unlike std::auto_ptr.


    I suppose that makes sense.

    (OTOH, it might be a bit more obfuscated to get an error message related
    to some private member of a class when you try to copy instances of it,
    than it would be to get a direct error message that says "sorry, the copy
    constructor / assignment operator of this class is not accessible". If you
    want to make it more explicit that you really have disabled copying, then
    you would declare the copy constructor / assignment operator private, in
    which case it doesn't really matter if you use scoped_ptr, auto_ptr or
    something else for your polymorphic Pimpl opject...)
     
    Juha Nieminen, Jul 20, 2010
    #11
  12. Juha Nieminen

    Öö Tiib Guest

    On 20 juuli, 13:17, Juha Nieminen <> wrote:
    > Marcel Müller <> wrote:
    > > Did you ever succeed to instantiate a polymorphic object on the stack?
    > > Probably not. The exact type must be known at compile time for this
    > > purpose. So, no factory pattern.

    >
    >   If you don't know the actual type of the object at compile time in
    > the current scope, but nevertheless want to use scoped_ptr to handle
    > it, it would mean that there has to be some function which you call from
    > the current scope and which returns a raw pointer to the object it
    > allocated (leaving the responsibility of deleting the object up to the
    > calling code). While this is certainly something you can do, I would say
    > it's a pretty bad design (allocating something and then leaving the
    > deletion up to the calling code is asking for trouble in a non-garbage-
    > collected environment).


    Yes, usually producing factory is in pair with recycling factory, but
    not always. When there is such pair then boost::shared_ptr is better
    since you can attach deleter (recycling factory) to it. I am not sure
    why deleter can not be attached to boost::scoped_ptr, makes me to use
    shared_ptr too often for RAII and in wrong place (for something i do
    not want to be shared).

    >   If I understood correctly, that "factory" function can certainly not
    > return a scoped_ptr (because it's non-copyable).
    >
    > Of course it could take a scoped_ptr reference as parameter and put
    > the allocated object there. Feels a bit contrived, though.


    Factory can return raw pointer. Factory pattern is most elegant when
    you have an input (lets say stream) whose contents you know that will
    form some Animal, but not sure if it is a Cat or a Dog or a Frog.

    > > The lifetime of stack objects is restricted to {} blocks.

    >
    >   So is the lifetime of an object handled by scoped_ptr (the object cannot
    > be shared nor transferred to anything else). So?


    It can be ptr.reset() or even ptr.reset(to_something_else) before
    going out of scope.
     
    Öö Tiib, Jul 20, 2010
    #12
  13. On 20 juil, 12:22, Juha Nieminen <> wrote:
    > Öö Tiib <> wrote:
    > > On 19 juuli, 18:10, Juha Nieminen <> wrote:
    > >>   Can someone give me an example where it makes any sense to use
    > >> boost::scoped_ptr?

    >
    > > There is nothing better for a polymorphic component of object.
    > > boost::scoped_ptr data member automatically disables default
    > > assignment and copy construction unlike std::auto_ptr.

    >
    >   I suppose that makes sense.
    >
    >   (OTOH, it might be a bit more obfuscated to get an error message related
    > to some private member of a class when you try to copy instances of it,
    > than it would be to get a direct error message that says "sorry, the copy
    > constructor / assignment operator of this class is not accessible". If you
    > want to make it more explicit that you really have disabled copying, then
    > you would declare the copy constructor / assignment operator private, in
    > which case it doesn't really matter if you use scoped_ptr, auto_ptr or
    > something else for your polymorphic Pimpl opject...)


    But it make sense if you forgot to handle the copy semantic.

    As an extra, you don't need to add the destruction of the pointed
    object in the destructor, which improve somewhat the locality of code
    changes.

    --
    Michael
     
    Michael Doubez, Jul 20, 2010
    #13
  14. Juha Nieminen

    Öö Tiib Guest

    On 20 juuli, 13:22, Juha Nieminen <> wrote:
    > Öö Tiib <> wrote:
    > > On 19 juuli, 18:10, Juha Nieminen <> wrote:
    > >>   Can someone give me an example where it makes any sense to use
    > >> boost::scoped_ptr?

    >
    > > There is nothing better for a polymorphic component of object.
    > > boost::scoped_ptr data member automatically disables default
    > > assignment and copy construction unlike std::auto_ptr.

    >
    >   I suppose that makes sense.
    >
    >   (OTOH, it might be a bit more obfuscated to get an error message related
    > to some private member of a class when you try to copy instances of it,


    Depends on compiler perhaps. I think most will just say that you do
    not have copy constructor or assignment operator of class available
    and not drop too deeply into details why it is so.

    > than it would be to get a direct error message that says "sorry, the copy
    > constructor / assignment operator of this class is not accessible". If you
    > want to make it more explicit that you really have disabled copying, then
    > you would declare the copy constructor / assignment operator private, in
    > which case it doesn't really matter if you use scoped_ptr, auto_ptr or
    > something else for your polymorphic Pimpl opject...)


    OK, may be matter of taste. I like complex class interface definition
    arranged like that:

    class Something // :,, possible bases
    {
    public:
    // ... interface type defs
    public:
    Something(); // may be missing
    Something(Something const& that); // may be missing
    // ... other constructors
    virtual ~Something(); // may be missing
    Something& operator=(Something const& that); // may be missing
    // **comment**
    // ... rest of public interface
    // ... is sometimes not that short
    protected:
    // ...
    private:
    // ...
    };

    Like you see private section is at bottom and i do everything i can to
    not make someone who just wants to use the class for something not to
    need to read the protected section or below. There are too lot of
    possible class layouts to make interface intuitive without commenting
    construction/destruction/copying within public section.

    That **comment** therefore explains all oddities of construction/
    destruction/copying. What about missing ones from that section? Are
    default, compiler-generated things OK? Why? Was something from default
    interface disabled by something? Why? Was something moved to non-
    public for some reason? Why? Are there factories/recyclers? Why?
    Where? ... so on.

    It is perhaps matter of taste, but i feel it is one place where i am
    pondering "why? .. why? ... wtf?" most often when looking at someones
    class definition and comments help there greatly. This pondering gets
    boring after a while when there are hundreds of classes.
     
    Öö Tiib, Jul 20, 2010
    #14
  15. Juha Nieminen

    Öö Tiib Guest

    On 20 juuli, 13:55, Öö Tiib <> wrote:
    > On 20 juuli, 13:17, Juha Nieminen <> wrote:
    > > Marcel Müller <> wrote:
    > > > The lifetime of stack objects is restricted to {} blocks.

    >
    > >   So is the lifetime of an object handled by scoped_ptr (the object cannot
    > > be shared nor transferred to anything else). So?

    >
    > It can be ptr.reset() or even ptr.reset(to_something_else) before
    > going out of scope.


    Note ... quite often the constructors may throw. Your algorithm may
    have ways to survive some of exceptions (for example by retrying). Not
    too convenient to write usage of automatic object whose constructor
    may throw survivable exceptions?
     
    Öö Tiib, Jul 20, 2010
    #15
  16. On 20 juil, 14:22, Öö Tiib <> wrote:
    > On 20 juuli, 13:55, Öö Tiib <> wrote:
    >
    > > On 20 juuli, 13:17, Juha Nieminen <> wrote:
    > > > Marcel Müller <> wrote:
    > > > > The lifetime of stack objects is restricted to {} blocks.

    >
    > > >   So is the lifetime of an object handled by scoped_ptr (the object cannot
    > > > be shared nor transferred to anything else). So?

    >
    > > It can be ptr.reset() or even ptr.reset(to_something_else) before
    > > going out of scope.

    >
    > Note ... quite often the constructors may throw. Your algorithm may
    > have ways to survive some of exceptions (for example by retrying). Not
    > too convenient to write usage of automatic object whose constructor
    > may throw survivable exceptions?


    It depends. If they are swapable, I may prefer to keep them on the
    stack.

    There are also strategies using in-place new (in the spirit of Barton-
    Nackman's fallible) that can handle it quite easily.

    --
    Michael
     
    Michael Doubez, Jul 20, 2010
    #16
  17. Juha Nieminen

    Öö Tiib Guest

    On 20 juuli, 15:53, Michael Doubez <> wrote:
    > On 20 juil, 14:22, Öö Tiib <> wrote:
    >
    >
    >
    > > On 20 juuli, 13:55, Öö Tiib <> wrote:

    >
    > > > On 20 juuli, 13:17, Juha Nieminen <> wrote:
    > > > > Marcel Müller <> wrote:
    > > > > > The lifetime of stack objects is restricted to {} blocks.

    >
    > > > >   So is the lifetime of an object handled by scoped_ptr (the object cannot
    > > > > be shared nor transferred to anything else). So?

    >
    > > > It can be ptr.reset() or even ptr.reset(to_something_else) before
    > > > going out of scope.

    >
    > > Note ... quite often the constructors may throw. Your algorithm may
    > > have ways to survive some of exceptions (for example by retrying). Not
    > > too convenient to write usage of automatic object whose constructor
    > > may throw survivable exceptions?

    >
    > It depends. If they are swapable, I may prefer to keep them on the
    > stack.
    >
    > There are also strategies using in-place new (in the spirit of Barton-
    > Nackman's fallible) that can handle it quite easily.


    Perhaps i lost track how. Can you paste some sample elegant example? I
    may be wrong but it feels like by using some sort of two-phase
    construction with default constructor producing useless/invalid
    object? There are cases when missing value is important, useful and
    valid state of object (scientific computing). On other cases i usually
    prefer a pointer that is NULL (or exception) to any ways to produce
    invalid object with missing value. The placement news, swaps and
    invalid state (when not natural) cause confusion to average
    programmer, slow him down and i do not have time to maintain
    everything myself.
     
    Öö Tiib, Jul 20, 2010
    #17
  18. On 20 juil, 16:30, Öö Tiib <> wrote:
    > On 20 juuli, 15:53, Michael Doubez <> wrote:
    >
    >
    >
    > > On 20 juil, 14:22, Öö Tiib <> wrote:

    >
    > > > On 20 juuli, 13:55, Öö Tiib <> wrote:

    >
    > > > > On 20 juuli, 13:17, Juha Nieminen <> wrote:
    > > > > > Marcel Müller <> wrote:
    > > > > > > The lifetime of stack objects is restricted to {} blocks.

    >
    > > > > >   So is the lifetime of an object handled by scoped_ptr (the object cannot
    > > > > > be shared nor transferred to anything else). So?

    >
    > > > > It can be ptr.reset() or even ptr.reset(to_something_else) before
    > > > > going out of scope.

    >
    > > > Note ... quite often the constructors may throw. Your algorithm may
    > > > have ways to survive some of exceptions (for example by retrying). Not
    > > > too convenient to write usage of automatic object whose constructor
    > > > may throw survivable exceptions?

    >
    > > It depends. If they are swapable, I may prefer to keep them on the
    > > stack.

    >
    > > There are also strategies using in-place new (in the spirit of Barton-
    > > Nackman's fallible) that can handle it quite easily.

    >
    > Perhaps i lost track how. Can you paste some sample elegant example? I
    > may be wrong but it feels like by using some sort of two-phase
    > construction with default constructor producing useless/invalid
    > object? There are cases when missing value is important, useful and
    > valid state of object (scientific computing). On other cases i usually
    > prefer a pointer that is NULL (or exception) to any ways to produce
    > invalid object with missing value. The placement news, swaps and
    > invalid state (when not natural) cause confusion to average
    > programmer, slow him down and i do not have time to maintain
    > everything myself.


    Something along the lines of:

    template< class T >
    class DelayedBuilder
    {
    public:
    DelayedBuilder():_valid(false){}
    // ensure RAII
    ~DelayedBuilder(){
    if(_isvalis)destroy();
    }

    // reinterpret union as T
    T& value(){ assert(_isvalid); return *((T*)_data.object);}

    // destroy object
    void destroy(){ assert(_isvalid); value().~T(); }

    // build object
    void build()
    { assert(!_isvalid); new (_data.object) (); _isvalid = true; }
    template<class P1> void build(P1 const & p1)
    { assert(!_isvalid); return new (_data.object) (p1); _isvalid =
    true; }
    template<class P1,class P2> void build(P1 const & p1, P2 const &
    p2)
    { assert(!_isvalid); return new (_data.object) (p1,2); _isvalid =
    true; }
    // and so one for build functions

    private:
    union{ stricter_alignement ; unsigned char object[ sizeof(T) ] ;}
    _data;
    bool _isvalid;
    };


    And the usage:

    // SocketStream has only constructor with (address,port)
    DelayedBuilder<SocketStream> socket;

    // try to build socket 3 times
    for( int i=0; i<3 ; ++i )
    {
    try {
    socket.build("127.0.0.23",4242);
    } catch(SocketConnectError const & e){
    continue;
    }
    ...
    }

    if( !socket.isValid() )
    {// failure
    return -1;
    }

    // ... use socket

    I don't say I would use it all over the place but it might have its
    use.

    --
    Michael
     
    Michael Doubez, Jul 20, 2010
    #18
  19. Juha Nieminen

    James Kanze Guest

    On Jul 20, 11:17 am, Juha Nieminen <> wrote:
    > Marcel Müller <> wrote:
    > > Did you ever succeed to instantiate a polymorphic object on the stack?
    > > Probably not. The exact type must be known at compile time for this
    > > purpose. So, no factory pattern.


    > If you don't know the actual type of the object at compile
    > time in the current scope, but nevertheless want to use
    > scoped_ptr to handle it, it would mean that there has to be
    > some function which you call from the current scope and which
    > returns a raw pointer to the object it allocated (leaving the
    > responsibility of deleting the object up to the calling code).


    Why? The function declaring the scoped_ptr can decide itself
    which class it wants to new. Don't forget that scoped_ptr
    supports reset, so you can do something like:

    boost::scoped_ptr p;
    if (someCondition)
    p.reset(new Type1);
    else (somethingElse)
    p.reset(new Type2);
    // and if neither is true, I have a null pointer...

    --
    James Kanze
     
    James Kanze, Jul 20, 2010
    #19
  20. Juha Nieminen

    Öö Tiib Guest

    On 20 juuli, 18:56, Michael Doubez <> wrote:
    > On 20 juil, 16:30, Öö Tiib <> wrote:
    >
    >
    >
    > > On 20 juuli, 15:53, Michael Doubez <> wrote:

    >
    > > > On 20 juil, 14:22, Öö Tiib <> wrote:

    >
    > > > > On 20 juuli, 13:55, Öö Tiib <> wrote:

    >
    > > > > > On 20 juuli, 13:17, Juha Nieminen <> wrote:
    > > > > > > Marcel Müller <> wrote:
    > > > > > > > The lifetime of stack objects is restricted to {} blocks.

    >
    > > > > > >   So is the lifetime of an object handled by scoped_ptr (the object cannot
    > > > > > > be shared nor transferred to anything else). So?

    >
    > > > > > It can be ptr.reset() or even ptr.reset(to_something_else) before
    > > > > > going out of scope.

    >
    > > > > Note ... quite often the constructors may throw. Your algorithm may
    > > > > have ways to survive some of exceptions (for example by retrying). Not
    > > > > too convenient to write usage of automatic object whose constructor
    > > > > may throw survivable exceptions?

    >
    > > > It depends. If they are swapable, I may prefer to keep them on the
    > > > stack.

    >
    > > > There are also strategies using in-place new (in the spirit of Barton-
    > > > Nackman's fallible) that can handle it quite easily.

    >
    > > Perhaps i lost track how. Can you paste some sample elegant example? I
    > > may be wrong but it feels like by using some sort of two-phase
    > > construction with default constructor producing useless/invalid
    > > object? There are cases when missing value is important, useful and
    > > valid state of object (scientific computing). On other cases i usually
    > > prefer a pointer that is NULL (or exception) to any ways to produce
    > > invalid object with missing value. The placement news, swaps and
    > > invalid state (when not natural) cause confusion to average
    > > programmer, slow him down and i do not have time to maintain
    > > everything myself.

    >
    > Something along the lines of:
    >
    > template< class T >
    > class DelayedBuilder
    > {
    >    public:
    >      DelayedBuilder():_valid(false){}
    >      // ensure RAII
    >      ~DelayedBuilder(){
    >          if(_isvalis)destroy();
    >      }
    >
    >      // reinterpret union as T
    >      T& value(){ assert(_isvalid); return *((T*)_data.object);}
    >
    >      // destroy object
    >      void destroy(){ assert(_isvalid); value().~T(); }
    >
    >      // build object
    >      void build()
    >      { assert(!_isvalid); new (_data.object) (); _isvalid = true; }
    >      template<class P1> void build(P1 const & p1)
    >      { assert(!_isvalid); return new (_data.object) (p1); _isvalid =
    > true;  }
    >      template<class P1,class P2> void build(P1 const & p1, P2 const &
    > p2)
    >      { assert(!_isvalid); return new (_data.object) (p1,2); _isvalid =
    > true;  }
    >      // and so one for build functions
    >
    >    private:
    >      union{ stricter_alignement ; unsigned char object[ sizeof(T) ] ;}
    > _data;
    >      bool _isvalid;
    >
    > };
    >
    > And the usage:
    >
    > // SocketStream has only constructor with (address,port)
    > DelayedBuilder<SocketStream> socket;
    >
    > // try to build socket 3 times
    > for( int i=0; i<3 ; ++i )
    > {
    >   try {
    >   socket.build("127.0.0.23",4242);
    >   } catch(SocketConnectError const & e){
    >     continue;
    >   }
    >   ...
    >
    > }
    >
    > if( !socket.isValid() )
    > {// failure
    >  return -1;
    >
    > }
    >
    > // ... use socket
    >
    > I don't say I would use it all over the place but it might have its
    > use.


    Oh, you meant in a template that adds valid state externally. Sure,
    there may be reasons when such template may be better performing than
    boost::scoped_ptr<>. It is perhaps somewhat like boost:eek:ptional<>?
    Performance optimizations are usually in later list of things to do
    and average team mate does not usually apply to maintain templates
    anyway. I usually take such things from boost since it is usually well-
    tested and so does rarely need maintenance.

    As for performance ... all know when dynamics really start to hurt
    performance. Worst case is when the object state is small (lets say
    one double in it) but we have large containers of such. Vector of
    scoped_ptr's may be lost case there. However DelayedBuilder's are also
    questionable since these will effectively double up the needed storage
    size compared to just vector of such objects. Therefore using NaN
    value of that double state for indicating if the object is invalid
    might be lot better performance optimization.
     
    Öö Tiib, Jul 20, 2010
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    743
    Joe Gottman
    Jan 21, 2006
  2. kathy
    Replies:
    2
    Views:
    353
    Jeff Flinn
    Apr 12, 2006
  3. none
    Replies:
    6
    Views:
    1,054
    Dizzy
    Jul 11, 2007
  4. zs0723

    about boost::scoped_ptr

    zs0723, Mar 5, 2008, in forum: C++
    Replies:
    10
    Views:
    2,526
    James Kanze
    Mar 7, 2008
  5. Vimal
    Replies:
    3
    Views:
    4,752
Loading...

Share This Page