Why throw a class over an enum? - c++

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.

Related

How to add error checking in a class member function?

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.

std::any by std::exception_ptr

Probably I am not the first person finding out that std::exception_ptr could be used to implement an any type (performance considerations being put aside), as it is probably the only type in C++ that can hold anything. Googling did not, however, bring any result in this direction.
Does anybody know whether the following approach has been used anywhere for anything useful?
#include <exception>
#include <iostream>
struct WrongTypeError : std::exception { };
class Any {
public:
template <class T>
void set (T t) {
try { throw t; }
catch (...) { m_contained = std::current_exception(); }
}
template <class T>
T const & get () {
try { std::rethrow_exception (m_contained); }
catch (T const & t) { return t; }
catch (...) { throw WrongTypeError {}; }
}
private:
std::exception_ptr m_contained = nullptr;
};
int main () {
auto a = Any {};
a.set (7);
std::cout << a.get<int> () << std::endl;
a.set (std::string {"Wonderful weather today"});
std::cout << a.get<std::string> () << std::endl;
return 0;
}
as it is probably the only type in C++ that can hold anything.
I'm afraid this is not the case. boost::any can hold any type, and even copies (assume the type is copyable) it correctly as well. It is implemented (broadly speaking) using a base class and a templated child:
class any_base {
...
}
template <class T>
class any_holder : public any_base
{
private:
T m_data;
}
From this you can imagine that you can stuff any type into an any_holder (with the right interface), and then you can hold an any_holder by pointer to any_base. This technique is a type of type erasure; once we have an any_base pointer we are holding an object but don't know anything about the type. You could say this is total type erasure, something like std::function provides partial type erasure (and may use similar techniques under the hood, I'm not sure off the top of my head).
boost::any provides additional interface to support its usage of holding any type, and it probably provides better performance as throwing exceptions is crazy slow. Also, as I mentioned before, it correctly copies the underlying object, which is pretty cool. exception_ptr is a shared ownership pointer, so I believe it makes shallow copies instead.
Boost any website: http://www.boost.org/doc/libs/1_59_0/doc/html/any.html
It's being considered for the standard I believe: http://en.cppreference.com/w/cpp/experimental/any
It seems like the implementation is similar to boost but adds a small object optimization.
exception_ptr is quite a strange beast as far as I can tell, I've come across it before and googled it and there's surprisingly little information out there. I'm pretty sure however that it's magical, i.e. it cannot be implemented in userspace. I say this because when you throw it, the type seems to magically unerase itself, this isn't generally possible.
You are certainly the first person I have come across who has thought of it.
I'm definitely impressed by your lateral thinking skills :)
There is a problem with this approach however, (other than the obvious performance problem).
This stems from the fact that throw is permitted to make a copy of the object thrown.
Firstly this places a restriction on what you may store in your 'any' class, secondly it will have further performance implications and thirdly, each time you access your object, the compiler is not obliged to give you the same one. It's allowed to give you a copy. This means that at the very least you should only store immutable objects this way. (Note: when I say 'should' I really mean 'absolutely should not!') :)
You could get around this by crafting a class that allocates memory to store the object, records it's type and deletes it properly... But if you did that you'd be better off without the exception complication anyway.
In any case, this is what boost::any does under the covers.

Throwing anonymous exception subclass

I was playing with c++ exceptions and I've tried throwing an anonymous exception like this:
throw class : public std::exception
{
virtual const char *what() const noexcept
{
return "Custom exception";
}
} ex;
However I'm getting the following error when trying to compile:
error: expected primary-expression before ‘class’
throw class : public std::exception
^
My compiler is gcc 5.2.1 on Linux x86_64.
How can I achieve the desired result?
This is not an answer per-se, but some important information what will help you going forward:
First, throwing an anonymous exception is unlikely to be useful. Exceptions are caught by their type. If you can't name the type, you can't catch the exception explicitly - only by its base, in which case you may as well have just thrown the base.
Second (and this is important):
There's rarely a good reason to derive from std::exception directly. You should derive from one of the exception types defined in <stdexcept>
these are:
std::runtime_error - indicating that some runtime condition makes it impossible to perform the service at the moment (such as a missing file).
std::logic_error - indicating that what was attempted will never be possible and the program is fundamentally in error in a way that could not be detected at compile time.
Handy reference here:
http://en.cppreference.com/w/cpp/header/stdexcept
You can't declare a class in a throw statement. Declare the class first (anonymously if you like, naming it via a typedef), then you can throw it.
Better is to name the exception class, but put it in the nameless namespace:
namespace {
class LocalException : public std::exception {
const char *what() const noexcept override {
return "Custom exception";
}
};
}
....
throw LocalException();
or, if you insist, you can create an object of anonymous class, and throw that.
static class : public std::exception {
const char *what() const noexcept override {
return "Custom exception";
}
} LocalExceptionObject;
....
throw LocalExceptionObject;
Edit If you create a typedef, somebody can copy it, and it names the same class. You have to create an object of the anonymous class, and then nobody can name it.
Having said that, I don't think having anonymous things is useful. Far better to declare the class in a nameless namespace (so you know it is private), and just use it.

Catching a Boost exception and extracting its message

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.

Boost rethrow_exception throws exception of different type

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.