Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly throw an exception which needs more than just a constructor?

I have an Exception class on which I want to set more information before I throw it. Can I create the Exception object, call some of its functions and then throw it without any copies of it being made?

The only method I've found is throwing a pointer to the object:

class Exception : public std::runtime_error
{
public:
    Exception(const std::string& msg) : std::runtime_error(msg) {}
    void set_line(int line) {line_ = line;}
    int get_line() const {return line_;}
private:
    int line_ = 0;
};

std::unique_ptr<Exception> e(new Exception("message"));
e->set_line(__LINE__);
throw e;
...
catch (std::unique_ptr<Exception>& e) {...}

But throwing exceptions by pointer is generally avoided, so is there any other way?

There is also the option of setting all the options through the constructor, but this can quickly become unscalable if more fields are added to the class and you want to have fine-grained control over what fields to set:

throw Exception("message"); // or:
throw Exception("message", __LINE__); // or:
throw Exception("message", __FILE__); // or:
throw Exception("message", __LINE__, __FILE__); // etc.
like image 869
Claudiu Avatar asked Apr 03 '17 12:04

Claudiu


People also ask

How do you handle an exception that is thrown from the constructor?

Exceptions: Exceptions in Constructors When throwing an exception in a constructor, the memory for the object itself has already been allocated by the time the constructor is called. So, the compiler will automatically deallocate the memory occupied by the object after the exception is thrown.

Is throwing exception from constructor accepted as a good practice?

Can a Constructor Throw an Exception in Java? This can help to prevent the object from being instantiated if the data will not be valid. This can help to prevent bugs and bad data. Throwing exceptions is especially important in constructors because of how it affects instantiating the object.

How do you throw an exception correctly?

Throwing an exception is as simple as using the "throw" statement. You then specify the Exception object you wish to throw. Every Exception includes a message which is a human-readable error description. It can often be related to problems with user input, server, backend, etc.

In which case is it necessary to have constructors which throw exceptions?

A constructor should throw an exception when it is unable to complete the construction of said object.


2 Answers

C++ exception classes are expected to be copyable or at least movable. In your example, making your class copyable is a matter of adding a default copy constructor:

Exception(Exception const&) = default;

If you need to encapsulate some non-copyable and non-movable state in your exception class, wrap such state into std::shared_ptr.

like image 112
Joseph Artsimovich Avatar answered Oct 17 '22 03:10

Joseph Artsimovich


You can create a data-holding class, like ExceptionData. Then create ExceptionData object and call it's methods. Then create Exception object using std::move in ctor like:

ExceptionData data;
data.method();
throw Exception(std::move(data));

Of course, ExceptionData needs to be movable and you have to have ctor that accepts ExceptionData && (rvalue reference).

It'll work if you really need to avoid copies, but to me it feels like preliminary optimization. Think how often exceptions are being thrown in your app and is it really worth it to complicate things for that matter.

like image 45
Aleksei Petrenko Avatar answered Oct 17 '22 02:10

Aleksei Petrenko