Re: boost::scoped_ptr rationale?
On 20 juuli, 18:56, Michael Doubez <michael.dou...@free.fr> wrote:
On 20 juil, 16:30, =D6=F6 Tiib <oot...@hot.ee> wrote:
On 20 juuli, 15:53, Michael Doubez <michael.dou...@free.fr> wrote:
On 20 juil, 14:22, =D6=F6 Tiib <oot...@hot.ee> wrote:
On 20 juuli, 13:55, =D6=F6 Tiib <oot...@hot.ee> wrote:
On 20 juuli, 13:17, Juha Nieminen <nos...@thanks.invalid> wrote:
Marcel M=FCller <news.5.ma...@spamgourmet.com> 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); _isvali=
d =
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:optional<>?
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.