Avoiding heap allocation with throwing constructors
Let's say I have a class Foo
that does not define a default throws
constructor and in a non-standard constructor. When initializing a new object of the type, I would like to catch any exceptions and return, otherwise continue using the object. I notice that it is difficult, if not impossible, to initialize this object on the stack or using a shared pointer because I am trying to avoid memory management.
Error 1
Foo f; // doesn't work, no default constructor
try { f = Foo(...); }
Error 2
try {
Foo f(...)
}
catch(...) {}
// doesn't work, f is inaccessible
Error 3
boost::shared_ptr<Foo> pf;
try { pf = new Foo(...); } // no assignment operator
Should I...
Foo *f;
try { f = new Foo(...) } // okay, let just manage the memory
Is there a way?
Edit
Ok, this is how it works, although not the cleanest. Is there a more "standard" way?
boost::shared_ptr<Foo> pf;
try { pf = boost::shared_ptr<Foo>(new Foo(...)); }
source to share
One solution might be to use boost::optional
(or C ++ 14 std::optional
):
boost::optional<Foo> f;
try { f = Foo(...); }
source to share
Your smart pointer is up and running fine if you use the correct .reset () method.
However, the question is not appropriate for normal use cases, either the class is incorrectly designed or you are using it incorrectly. Normal use should just go ahead like case # 1 with an F inside the block. Or don't try to block and leave the catch upstream.
EDIT: Referring to the latest comments as well as the original issue, I maintain my position that blocking attempts in end-user code are discouraged. In situations where I use third-party components with a specific throwing strategy, if that doesn't suit my needs, I write wrappers converting the exception to an error exception or an error code exception. And use this advanced component.
In this case, the user is concerned about throwing the ctor. So this will be handled by wrapping the ctor in a function:
Foo* new_foo( ARGS )
{
try{
return new Foo( ARGS );
}
catch( const FooException& )
{
return NULL;
}
}
Then you have client code free of try blocks and more importantly, no assignments. It will just be const unique_ptr<Foo> p(new_foo(...))
.
source to share