For error handling, exceptions are problematic for me because my code is going to be a dynamically linked library. Furthermore I think exceptions should only be used in exceptional cases. But I will have cases where an error might occur that is not exceptional. Another problem is that my library will be called from C#. So using exceptions for all errors does not seem the right choice here.
But I find the concept of std::error_code and std::error_category quite pleasant and would like to use it in my application. However, I would also like to offer some kind of stack trace for errors.
Consider an example: The user wants to load a domain object from a database. To load this domain object the application needs to load rows from different tables. Suppose one of the required rows cannot be found. In this case the database layer would generate some "not found" error. If i propagate this error all up to the user the error message will not be very helpful because nobody knows what was not found. Likewise, if each layer handles the errors of the lower layer and generates a corresponding new error, abstracting the low level error, I would end up with something like "unable to load from database" which again is not very helpful. What I would like is to have both. That is each layer abstracts errors it gets from any lower level to be able to display descriptive messages to the end user but at the same time I don't want to lose information about the low level error. So I would like to have something like an error stack trace.
I thought about deriving from std::error_code and extend the class with a pointer to an underlying std::error_code and methods to get all these underlying objects. However, I am not sure if this technique would be a good idea because I read that care was taken when designing std::error_code to make it efficient.
We want error_code to be a value type that can be copied without slicing and without requiring heap allocation, but we also want it to have polymorphic behavior based on the error category.
EDIT I now think this technique would also introduce slicing problems, wouldn't it?
EDIT 2 I now think to implement it by deriving from std::error_code. Instead of a pointer, what would need heap allocation somewhere, my derived class would have a boost::optional. This way the inner error code could be created on the stack simply by copying it. A non-existing inner error code could be represented by boost::optional correctly. Slicing would still be a problem but I guess it is neglectable because the case of assigning an instance of my derived class to a std::error_code variable would not be necessary and even if it happens I would only loose information about the inner error codes. Furthermore I could provide a conversion from std::error_code to my derived class that has no inner error codes.
EDIT 3 I didn't think of that it is not possible to have a class containing a boost::optional of itself. So right now I don't see any possibility for what I would like to have without an allocation on the heap.
std::exceptionderived exception class with aninner_exception()method to return the inner exception (originated from lower level)? Your UI may even catch abusiness_exceptionbut navigating throughinner_exception()you may log everything did happen in each layer (well, if you want to do that, there may be security reasons to do not expose underlying details).std::error_codeandstd::error_categoryaren't right concept for your scenario. Application should use exceptions to notify errors, error codes are a heritage of a non-C++ environment (for example Operating System API or device drivers). In this case IMO you should create a wrapper around that functions encapsulating their error codes withstd::error_code; expose them with a C++ish interface then manage errors in your application using exceptions (with your own exception with aerror_code()member to get low level error code (if any).std::error_codewon't work (and you have to go back to anint). If for any reason you want to rely on error codes (but they should be used for compatibility only, IMO) then you can apply same technique (error_codeis a non sealed class)