I have a class whose constructor may throw an exception. Here’s some code that will catch the exception:
try {
MyClass instance(3, 4, 5);
}
catch (MyClas
Dynamically allocate the instance using new
:
std::unique_ptr<MyClass> instance;
try
{
instance.reset(new MyClass(3, 4, 5));
}
catch (const MyClassException& ex)
{
std::cerr << "There was an error creating the MyClass." << std::endl;
return 1;
}
// use instance as needed...
A variant of Remy's answer, but saving a dynamic allocation using std::optional
:
std::optional<MyClass> instance_opt;
try {
// could use `instance = MyClass(3, 4, 5)`, but that requires you to write a move constructor
instance_opt.emplace(3, 4, 5);
}
catch (const MyClassException& ex) {
std::cerr << "There was an error creating the MyClass." << std::endl;
return 1;
}
MyClass& instance = *instance_opt;
// use instance as needed...
You should be doing everything you need to do inside the try
block:
try {
MyClass instance(3, 4, 5);
// Use instance here
}
catch (MyClassException& ex) {
cerr << "There was an error creating the MyClass." << endl;
return 1;
}
After all, it is only within the try
block that instance
has been successfully created and so can be used.
I do wonder whether your catch
block is really handling the exception. If you can't do anything to resolve the situation, you should be letting it propagate.
You could use a generic helper function that catches exceptions and the future std::optional
(or boost::optional
) to signal the successful or failed creation of the instance:
template< typename T, typename... Args >
std::optional< T > try_make( Args&&... args )
{
try {
return T{ std::forward< Args >( args )... };
}
catch( ... ) {
return {};
}
}
Using basically this:
auto instance = try_make< MyClass >(3, 4, 5);
Where instance
is now an optional<MyClass>
. To test the result and separate availablity of the instance from the error case is also simple:
if( auto instance = try_make< MyClass >( 3, 4, 5 ) ) {
// use *instance, but this code is *not* in the try/catch block!
}
else {
// creating the instance failed
}
Of course the exception information will be lost this way, but you could go for a less generic function and add some logging in the catch-block depending on your needs.