Reputation: 1147
Say I have some class Foo
which does not define a default constructor and throws
in a non-default constructor. When initializing a new object of the type, I'd like to catch any exceptions and return, otherwise continue using the object. I'm noticing it difficult, if at all possible, to initialize this object on the stack or through use of a shared pointer, because I'm trying to avoid managing memory.
Fail 1
Foo f; // doesn't work, no default constructor
try { f = Foo(...); }
Fail 2
try {
Foo f(...)
}
catch(...) {}
// doesn't work, f is inaccessible
Fail 3
boost::shared_ptr<Foo> pf;
try { pf = new Foo(...); } // no assignment operator
Must I...
Foo *f;
try { f = new Foo(...) } // okay, let's just manage the memory
Is there a way?
Edit
Okay, so this works, albeit not the cleanest. Is there a more "standard" way?
boost::shared_ptr<Foo> pf;
try { pf = boost::shared_ptr<Foo>(new Foo(...)); }
Upvotes: 2
Views: 217
Reputation: 17163
Your smart pointer case and likes work fine if you use the proper .reset() method.
However the question does not fit normal use cases, either the class is misdesigned or you use it incorrectly. Normal use should just go ahead like case#1 with F inside the block. Or without try block and leaving catch to upstream.
EDIT: Addressing recent comments as well as original issue, I keep my position that try blocks in end-user code are not welcome. For situations where I deal third-party components with certain throw strategy, if it does not fit my needs I write wrappers, converting exception to error-return or error code throwing exception. And use that extended component.
For this case the user is bothered by throwing ctor. So it would be handled by wrapping the ctor in a function:
Foo* new_foo( ARGS )
{
try{
return new Foo( ARGS );
}
catch( const FooException& )
{
return NULL;
}
}
Then have the client code free of try blocks, and more importantly, free of assignments. Just const unique_ptr<Foo> p(new_foo(...))
will do.
Upvotes: 1
Reputation: 227420
One solution could be to use boost::optional
(or C++14's std::optional
):
boost::optional<Foo> f;
try { f = Foo(...); }
Upvotes: 2
Reputation: 171127
The correct approach to keep f
stack-based is to respect the scope:
try {
Foo f(...);
... entire code using f ...
}
catch(...) {}
Upvotes: 2
Reputation: 15069
Smart pointers have a reset
method:
boost::shared_ptr<Foo> f;
//...
f.reset(new Foo(...));
This solves your "Fail #3" and allows you to do what you want.
Upvotes: 3