Given a class and one of its member functions like this:
// constructor
class Stitcher::Stitcher(const std::vector<cv::Mat> imgs)
{
calibrate(imgs);
}
// one of its member functions that gets called upon construction
void Stitcher::calibrate(const std::vector<cv::Mat> imgs)
{
// Do some stuff here
}
When constructing this Stitcher object, it runs the calibrate function upon construction. However calibrate will sometimes fail and I need a way to handle such failures. I was thinking of returning a boolean but wasn't sure how to do that because I still need access to the Stitcher object for other member functions. Basically I am instantiating it like this currently: Stitcher stitcher(images); which works fine as long as it doesn't fail. Then I can use stitcher.stitch(), stitcher.otherFunction(), etc. Any suggestions for this C++ newbie on how to handle errors inside a class member function?
There is a RAII (Resource Acquisition Is Initialization) idiom which is highly recommended in C++. One of the aspects of the RAII is the idea that there should not exist badly constructed or uninitialized objects. From your question I conclude that you are trying to initialize the object, but sometimes that is impossible. That is the application of RAII.
In C++ constructor functions don't return error codes, so there is another technique to handle errors: exceptions. In brief exception thrown from the constructor don't allow you to leave the not-constructed-yet object in a partially constructed state.
class Stitcher {
public:
Stitcher(const std::vector<cv::Mat> &imgs) {
calibrate(imgs);
// If the calibrate method fails, the object is not being constructed.
// The next line will not be executed on a non-calibrated object:
doSmthWithCalibratedImgs(imgs);
}
private:
void calibrate(const std::vector<cv::Mat> &imgs) {
// Do some stuff here
// if cannot calibrate:
throw exception("Cannot calibrate");
}
};
So the next task would be to handle possible exceptions from the code that constructs Stitcher objects.
Note that I've changed the signature of the methods to pass the vector by const reference: I guess that is what you need. Another thing that you might need is to store the imgs vector inside of the object as a data member, but that depends on the task and is up to you.
What you could do is throw an exception to indicate a problem that occurs during the execution of your program. The standard library has a number of exception classes that you could use for throwing an exception, all of which derive from std:exception. For example, std::out_of_range.
To throw a standard exception you create a string that describes the exception and use it to initialise the exception object:
std::string s("my exception")
...
throw std::out_of_range(s);
You can also write:
throw std::out_of_range("out of from somewhere");
using implicit conversion from char* to std::string.
Another possibility is to define your own special exception class, derived directly or indirectly from std::exception. However, you have to provide the overridden virtual function what() in your class:
class MyException: public std::exception
{
public:
MyException(...){
}
virtual const char* what() const throw() {
return "C++ Exception";
}
};
Another way to provide the what() function is to derive your exception class from one of the classes that have a string constructor for the what() argument:
class MyException: public std::out_of_range
{
public:
MyException(const std::string &what): std::out_of_range(what) {}
};
Like this you can different classes for different types of exceptions.
Now can you throw an exception in Stitcher::calibrate() but you have to have try...catch block to catch it. Something like this:
try
{
Stitcher stitcher;
// this will be executed if no exception is thrown
}
catch (const std::exception &e)
{
std::cout << e.what();
}
The first question you have to answer is (regarding your business logic): should failure of calibrate(imgs) also imply failure of constructing object of type Stitcher.
1. Possibility:
calibrate(imgs) fails, but the object is constructed. You would need some member methods (something like isCalibrated(..), recalibrate()... etc.), to be able to query object if the calibration was succesful, and maybe try to recalibrate if the predonditions are met at some other time, etc.
2. Possibility:
Stitcher constructor postcondition is, that calibration was successful. In this case, you can't tolerate the failure, so you have to throw exception within constructor.
Regarding this, you will maybe have to decide, what kind of exception safty guarantee you would aim to offer.
You have 3 choices here:
i) strong exception safety guarantee (best choice, if possible)
ii) basic exception safety gurantee (second best choice)
iii) no exception safety guarantee (worst choice)
Basically, doing work in the constructor is not a good practice. You could consider constructig Stitcher by setting up the required data members in the contructor and meet all necessary preconditions, and then provide some member methods like for ex. Calibrate()-with return false by failure, TryCalibrate()-which throws exception, etc., so the clients of Stitcher have better control about failure handling.
Related
In a code review recently, I had some less than kind words for something I thought awful. It turns out that it was obviously inspired by the QuantLib::Error class, which looks like this:
//! Base error class
class Error : public std::exception {
public:
/*! The explicit use of this constructor is not advised.
Use the QL_FAIL macro instead.
*/
Error(const std::string& file,
long line,
const std::string& functionName,
const std::string& message = "");
#ifdef QL_PATCH_MSVC_2013
/*! the automatically generated destructor would
not have the throw specifier.
*/
~Error() throw() override {}
#endif
//! returns the error message.
const char* what() const QL_NOEXCEPT override;
private:
ext::shared_ptr<std::string> message_;
};
Why is the member variable ext::shared_ptr<std::string> and not just plain std::string? What reason could there be to heap-allocate the string object itself? (The QuantLib code base seems to heap-allocate just about everything just about always just about everywhere, and pulls in shared_ptr's to cope with that - a classic anti-pattern - but doing it here as well "just for consistency" strikes me as a bit much. Am I missing something?)
This is following the behavior of standard library exception types.
They are supposed to be copyable without throwing exceptions, since throwing an exception during construction of an exception handler parameter would cause a call to std::terminate (and possibly in some other situations requiring a copy of the exception as well).
If std::string was used directly, copying the exception could cause for example a std::bad_alloc to be thrown. Using a reference-counted pointer instead avoids that.
When I catch an exception, I want to emit a signal and pass that exception to a slot so it can be handled in a different thread. The signal and slot are connected using a Qt:QueuedConnection type.
I first tried this:
/*in .h*/
signals:
void exceptionOccured(const std::exception &e);
public slots:
void exceptionReceive(const std::exception &e);
/*in .cpp*/
connect(this,SIGNAL(exceptionOccured(const std::exception&)),this,SLOT(exceptionReceive(const std::exception&)),Qt::QueuedConnection);
try {
throw std::runtime_error("test");
} catch (std::exception &e) {
emit exceptionOccured(e);
}
This somewhat works, but as QT makes a copy of the referenced object to be placed on the queue, the exceptionReceived slot receives a std::exception type object and all additional information is lost.
I then tried to pass a pointer to the original exception object, but that gives me the problem that by the time the slot is called the actual object has disappeared.
How can I either tell QT to make a correct copy of the exception (the actually application has multiple levels of inheritance from std::exception) or turn the catch'ed exception into some safe pointer type (i.e. copy it from the stack to the heap or so).
P.S.
The object sends the message to itself because the try/catch statement is run from a lambda function using QtConcurrent::run();
std::exception_ptrwas added to the standard one C++11 in order to solve exactly this problem. std::current_exception() lets you get a handle to the current exception, and you can then pass it around and re-throw it in any thread you want.
Details at http://en.cppreference.com/w/cpp/error/exception_ptr.
If you insist on using the base exception type, then this is a C++ problem, not a Qt problem. You'd need to implement some type of a virtual copy constructor pattern. Once you do, Qt will do the right thing automagically.
One such pattern:
class clonable_exception : public std::exception {
protected:
virtual void clone_to(clonable_exception& dst) const = 0;
public:
clonable_exception() = default;
clonable_exception(const clonable_exception& src) {
src.clone_to(*this);
}
clonable_exception & operator=(const clonable_exception& src) {
src.clone_to(*this);
}
};
All signals and slots should use the clonable_exception type instead of std::exception.
I'm writing a function, wd_sprintf, to provide a sprintf-like API. Under the covers, it uses the boost library.
If the user of wd_sprintf codes the format string improperly, boost::format will throw an exception. I'd like for my function to intercept the exception, repackage it in a message that identifies wd_sprintf as the locus of the error, and rethrows the exception.
What I can't figure out is what to catch, and how to extract the message.
// wd_sprintf(pattern [,args...]):
//
// This creates a temporary boost::format from pattern, and calls
// wd_sprintf_r() to recursively extract and apply arguments.
#include <boost/exception/all.hpp>
class wd_sprintf_exception : std::runtime_error {
public:
wd_sprintf_exception(string const& msg : std::runtime_error(msg) {}
};
template <typename... Params>
string
wd_sprintf (const string &pat, const Params&... parameters) {
try {
boost::format boost_format(pat);
return wd_sprintf_r(boost_format, parameters...);
}
catch (boost::exception e) {
const string what = string("wd_sprintf: ") + string(e.what());
throw wd_sprintf_exception(what);
}
}
Of course, this gets a compilation error because boost::exception is abstract.
(I've been to a number of sites and pages, including this one whose title was similar but which was full of '<<' operators inserting into a function call, template constructs like boost::get_error_info<my_tag_error_info>(e), and generally much more complexity than I suspect is really needed. I just need the above to work.)
You can't have an an automatic variable of an abstract type. You can, however, have a reference or pointer to one. The reason for this is that the compiler has no way of knowing exactly which derived type the variable actually is, so it doesn't know how much space to allocate for it or which class's copy constructor to use.
When you catch a boost::exception by value, as you're doing, the compiler has to make a local copy of it in your catch block; which it doesn't have enough information to do!
In your specific case, the best solution is to catch a reference to the original exception.
In regards to catching exceptions from Boost.Format, it throws exceptions derived from boost::io::format_error, which is derived from std::exception, not boost::exception. You should be catching boost::io::format_error.
I am using Boost exception_ptr's and observe that rethrow_exception(ptr) does not give me the original exception. I've cooked it down to this:
struct error : virtual std::exception, virtual boost::exception {};
try {
boost::exception_ptr ptr(boost::copy_exception(error()));
boost::rethrow_exception(ptr);
}
catch(boost::exception& e) {
// e is a boost::exception_detail::clone_impl<error>
}
Shouldn't e be of type error instead of type clone_impl?
I am using Boost 1.49.0.
It is by design.
See http://www.boost.org/doc/libs/1_55_0/libs/exception/doc/frequently_asked_questions.html, section "Why is boost::exception abstract?"
The type of boost::exception is abstract to prevent user from "rethrowing" it. If user wants to rethrow, she is forced to use code like
catch( boost::exception & e )
{
e << foo_info(foo);
throw; //Okay, re-throwing the original exception object.
}
You can also look at this from a different perspective. The customer error type can be almost anything, it may not allow derivation from it or may be non-copyable or non-constructable at all (e.g. private constructors only accessible to friends). Therefore, Boost cannot assume anything about customer's type, cannot copy or derive/copy from it and can only keep a pointer to the existing object passed to boost::copy_exception.
Just wondering, why is it better to throw a class over an enum
Surely throwing classes is more overhead?
e.g.
enum MyException
{
except_a,
except_b,
except_c
}
void function f(){
throw except_a;
}
int main(int arc, char* argv[]){
try{
} catch (MyException e){
switch(e){
except_a: break;
except_b: break;
except_c: break;
}
}
return 0;
}
Apart from the overhead. I also need to declare a class for each one which might override std::exception or something. More code, larger binary... what's the benefit?
Which of the following two catch blocks is easier to understand:
try {
do_something();
}
catch (const int&) {
// WTF did I catch?
}
catch (const std::out_of_range&) {
// Oh, something was out of range!
}
The name of an exception class should tell you something about why the exception was thrown; int doesn't tell you anything, you just know that you caught an int, whatever that means.
To consider your updated example of using an enumeration instead of an integer, which of the following is clearer:
try{
do_something();
}
// (1) Catch an enum:
catch (MyException e) {
switch(e) {
except_a: break;
except_b: break;
except_c: break;
default: throw; // Don't forget, you have to throw any exceptions
// that you caught but don't actually want to catch!
}
}
// (2) Catch specific exceptions
catch (const ExceptionA&) { }
catch (const ExceptionB&) { }
catch (const ExceptionC&) { }
There is no reason at all to prefer the first form: there's no performance benefit and the code is less clear and more error-prone. In your example, you forgot to rethrow the exception if you weren't handling it, so if someone later added an except_d exception to the MyException enumeration, you'd have unknowingly caught it.
As for your "overhead" question, it depends, but probably not. It should be (relatively) rare that an exception is thrown, and if you have a tight loop where performance really matters, you aren't going to be using exceptions anyway.
The benefit of using class hierarchies for exceptions is that they allow you to write clearer code, just like the benefit of using non-local control flow (exceptions) instead of other approaches like error code return values allows you to write clearer code (at least when you use exceptions correctly).
Given
enum MyException
{
except_a,
except_b,
except_c
}
write a catch clause that only catches except_c exceptions.
With
struct my_except {};
struct my_except_a : my_except {};
struct my_except_b : my_except {};
struct my_except_c : my_except {};
that's easy, since you can catch the base class or derived classes.
Many of the common advantages of derivation apply to exceptions. For example, base classed can stand in for derived classes and code needs to know only base classes to deal with derived exceptions. That's a form of polymorphism, while the enum is a switch over a type.
The general rule about polymorphism applies here, too: Whenever you are tempted to use a switch over a type, you are dismissing the advantages of polymorphism. The problems you are getting yourself into will be seen once the code has expanded to hundreds of kLoC, and you need to add a new type. With polymorphism, that's easy, because most code will be fine dealing with base class references only.
With the type enum, you have to hunt down every single switch statement over that enum and check whether you need to adapt it.
Things like these have killed more than one company.
Here's an afterthought: When they've done this for a while, users usually start to add all kinds of data to their exception types. A classic is to take __FILE__ and __LINE__ in an exception's constructor to be able to see where an exception came from. But this, too, needs exceptions to be class types.
A class can have things like an error message inside it, and can have a meaningful name that tells what kind of exception it represents. If you see an int being thrown, how can you tell what kind of error caused it?
The overhead in dispatching the exception is likely to be far more than copying a simple class. I measured it to be thousands of cycles in this question. So, performance is essentially moot.
Besides, an enum value as the sole member of a class is just as fast to copy as an enum value with no class around it. Exceptions can be like scratchpads for random notes to get out of a jam. It is just too likely that you'll want more data, which will at first (gasp) double the overhead to that of two ints' worth.
The easiest and best thing to do is to start with std:exception, and only EVER throw classes derived from it.
It is not about performance. Exception throwing is not the kinda thing you want to happen regularly in a CPU-intensive algorithm. And the overhead of unwinding the stack is way way more than the carry of the thrown object.
It is about being able to bundle the information about what kind of error occurred. It is about making it clear to the user of your library what you are throwing as an error and why. An integer or a float doesn't really carry much information.
Overhead doesn't matter, as exceptions are always expensive. An instance of a class can hold more information, and you can catch by bases.