Consider a class foo which has one or more functions which can report failure either through a logger or by throwing an exception if no logger was provided:
struct logger
{
// ...
};
struct foo
{
void set_logger(std::shared_ptr<logger> logger) { m_logger = std::move(logger); }
bool bar(const std::filesystem::path& path)
{
// Check path validity
if (not std::filesystem::exists(path) {
if (m_logger) {
m_logger->warn("path does not exist.");
return false;
}
else {
throw std::runtime_error("path does not exists.");
}
}
// Some random operation
try {
// Do something here that might throw
}
catch (const std::exception& e) {
if (m_logger) {
m_logger->warn("operation bar failed.");
return false;
}
else {
throw e;
}
}
return true;
}
private:
std::shared_ptr<logger> m_logger;
};
This does not only look ugly but is extremely error prone and as more functions are added to foo code will be repeditive.
Is there any kind of pattern or paradigm to abstract this logic away? Some kind of wrapper template I can construct to use inside foo's various functions when error reporting is needed?
Anything up to C++20 would be acceptable.
Is there any kind of pattern or paradigm to abstract this logic away? Some kind of wrapper template I can construct to use inside foo's various functions when error reporting is needed?
One thing you could do is to simply remove all the else { throw... } code and provide a default logger that throws an exception containing the logged message. If the client provides a different logger, fine, your code will use that; if not, it uses the default one. This scheme eliminates about half your error handling code and simplifies the flow while providing the same behavior, which seems like a positive outcome.
It's important to remember that logging a message is different from throwing an exception: it's often useful to be able to log a message that doesn't stop the flow of the program. So be sure to give your logger class methods that log without throwing as well; you might use a different log level for messages that are equivalent to exceptions.
Since your error case handling seems to follow the same structure, you could add a simple function that will do just that:
bool log_or_throw(logger * logger_, std::string const& message, std::exception const& exception) {
if (logger_) {
logger_->warn(message);
return false;
}
else {
throw exception;
}
}
And then you can change your error handling to a single line, probably making the flow a lot more readable:
if (not std::filesystem::exists(path) {
return log_or_throw(m_logger, "path does not exist.", std::runtime_error("path does not exists."));
}
Related
I'm wondering if it's generally a good practice to define your own exception classes for a given program. For example, I have a program that mainly does reading from/writing to files, and modifying iptables rules. I've written the program its own basic logger class as well. To handle unexpected values or errors such as opening files, I typically use std::runtime_error. I am wondering if defining my own exception classes is generally a good idea. Example:
void Protocol::set_port(const unsigned long &port) {
if ( (port > 0) && (port < 65535) ) {
port_ = port;
}
else {
throw std::invalid_argument("Invalid port number");
}
}
I don't like using a whole bunch of try and catch blocks, since I find it to be a bad and ugly practice (although I may be wrong).
I'm wondering if it's generally a good practice to define your own exception classes for a given program.
Yes, in general the exception's type should be descriptive of the source or cause, so you can handle that particular exception through pattern-matching rather than code.
I typically use std::runtime_error. I am wondering if defining my own exception classes is generally a good idea.
Yes, in general you should follow these rules:
Obviously, only use exceptions to report exceptional failures (i.e. a precondition not being met, or a resource being unavailable for reasons beyond your program's incorrect operation).
If the failure is a logical error (the caller is trying to do something illegal within your program's domain) then derive your exception from std::logic_error.
If the failure is a result of an invalid argument, then it would make sense to derived from std::invalid_argument.
If the failure is a runtime error (e.g. file missing) then derived from std::runtime_error.
It can also be useful to nest exceptions, since you can then pass both a summary and a cause of the exception for later diagnosis, example:
struct port_out_of_range : std::invalid_argument
{
port_out_of_range(std::string const& context, unsigned long given)
: std::invalid_argument(context + ": port given: " + std::to_string(given))
{
}
};
void Protocol::set_port(const unsigned long &port)
{
if ( port < 65535 ) {
port_ = port;
}
else {
throw port_out_of_range("Protocol::set_port", port);
}
}
... later ...
try {
// ... some things ...
foo.set_port(x);
// ... more things ...
}
catch(port_out_of_range& e)
{
// maybe some remedial action possible here
}
catch(std::exception& e)
{
// but not here
log(e);
throw;
}
I have external interface, let's say with 20 similar methods. Each can throw anything.
So, I have 20 methods looks like:
void Call3Wrapper(int& important_parameter)
{
try
{
external_namespace::IExternal::Call3(important_parameter);
}
catch(external_namespace::Exception& ex)
{
LogIt(ex, "Call3");
throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
LogIt(ex, "Call3");
throw mynamespace::MyException(ex);
}
catch(...)
{
LogIt("Unresolved exception", "Call3");
throw mynamespace::MyException("Unresolved exception");
}
}
And same for each Call1-Call20 (calls with different parameters).
Such as:
void Call7Wrapper(std::string& important_parameter)
void Call12Wrapper(bool& important_parameter, double&
important_parameter2)
...and etc.
I have nice function LogIt for all those cases, and our own type MyException, that handles all those cases also.
And all those 20 (40, 60) function's bodies looks ugly, because 90% of code is exactly similar try-catch checks. And a developer will die when he will need to fix anything same in all of them...
Does there exists a method / practice how to organize it less ugly way?
Something like lock-unlock-idiom in constructors&destructors, but for try-catch?
I definitely don't want to use #define CALLS_CATCH_BLOCK(call_name) ...
Maybe you can templatize the wrapper and call it via function objects:
template<typename CALLABLE_T>
void CallWrapper(CALLABLE_T callable, const char* name)
{
try
{
callable();
}
catch(external_namespace::Exception& ex)
{
LogIt(ex, name);
throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
LogIt(ex, name);
throw mynamespace::MyException(ex);
}
catch(...)
{
LogIt("Unresolved exception", name);
throw mynamespace::MyException("Unresolved exception");
}
}
Then you can use std::bind to create callable object with parameters, for example:
CallWrapper(std::bind(&external_namespace::IExternal::Call3,
std::ref(important_parameter)),
"Call3");
(or boost::bind/boost::ref for older compilers)
Note that the compiler will still generate an instantiation of the template for each different CALLABLE_T type, but you do not need to repeat the code.
Also note that this way you can also call and handle member functions of classes etc.
If this is to be used by an API interface, you might still need to create the separate methods, but call the templated wrapper internally instead of repeating the exception handling code.
I want to parse a simple text file and create an object from the data it contains. I'm using C++11 for this (and I'm not fluent).
In case of any kind of error (e.g. missing file or invalid text) I wish to tell the caller of my parsing function what went wrong, providing information like what kind of error occurred and where in the file.
I don't consider exceptional that errors occur while parsing, so it seems exceptions are not the way to go.
I thought of returning a struct with all the info, including the resulting parsed object in case of success:
struct ParsingResult
{
bool success;
int errorCode;
int errorLine;
ParsedObject object;
}
However I'm not convinced by this solution because, in case of errors, I must still provide a ParsedObject. I can define a default constructor for that, of course, but by it's nature a ParsedObject makes sense only when the parsing is successful.
I could change ParsedObject to ParsedObject*, but I'm reluctant to use pointers when not necessary, and I wonder if this can be avoided.
My question: can you suggest a better solution to this problem? What is it?
struct Obj
{
// your object from the data...
}
struct ParseError
{
int errorCode;
int errorLine;
}
class Parser
{
ParseError m_error;
// other things
public:
bool parse(const std::string& filename, Obj& parsedObject)
{
// Open file, etc...
//parsedObject.property1 = some_value;
// if something is wrong, set m_error and return false;
// return true if ok
}
ParseError getLastError() { return m_error; }
}
// in your code
Parser p;
Obj o;
if(!p.parse("filename", o))
{
// ParseError = p.getLastError();
}
You can use a
unique_ptr<ParsedObject>
or
shared_ptr<ParsedObject>
whose default constructor can be compared to null in case of unsuccessful parsing.
Avoiding raw pointers will free you from having to free memory :)
I have some kind of an ideological question, so:
Suppose I have some templated function
template <typename Stream>
void Foo(Stream& stream, Object& object) { ... }
which does something with this object and the stream (for example, serializes that object to the stream or something like that).
Let's say I also add some plain wrappers like (and let's say the number of these wrappers equals 2 or 3):
void FooToFile(const std::string& filename, Object& object)
{
std::ifstream stream(filename.c_str());
Foo(stream, object);
}
So, my question is:
Where in this case (ideologically) should I throw the exception if my stream is bad? Should I do this in each wrapper or just move that check to my Foo, so that it's body would look like
if (!foo.good()) throw (something);
// Perform ordinary actions
I understand that this may be not the most important part of coding and these solutions are actually equal, but I just wan't to know "the proper" way to implement this.
Thank you.
In this case it's better to throw it in the lower-level Foo function so that you don't have to copy the validation and exception throwing code in all of your wrappers. In general using exceptions correctly can make your code a lot cleaner by removing a lot of data validation checking that you might otherwise do redundantly at multiple levels in the call stack.
I would prefer not to delay notifying an error. If you know after you have created the stream, that it is no good, why call a method that works on it? I know that to reduce code-redundancy you plan to move it further down. But the downside of that approach is a less-specific error message. So this depends to some extent on the source-code context. If you could get away with a generic error message at the lower-function level you can add the code there, this will surely ease maintanence of the code especially when there are new developers on the team. If you need a specific error message better handle it at the point of failure itself.
To avoid code redundancy call a common function that makes this exception/error for you. Do not copy/paste the code in every wrapper.
The sooner you catch the exceptiont the better. The more specific the exception is - the better. Don't be scared of including most of your code into a try catch blocks, apart fromt he declaration.
For example:
int count = 0;
bool isTrue = false;
MyCustomerObject someObject = null;
try
{
// Initialise count, isTrue, someObject. Process.
}
catch(SpecificException e)
{
// Handle and throw up the stack. You don't want to lose the exception.
}
I like to use helper functions for this:
struct StreamException : std::runtime_error
{
StreamException(const std::string& s) : std::runtime_error(s) { }
virtual ~StreamException() throw() { }
};
void EnsureStreamIsGood(const std::ios& s)
{
if (!s.good()) { throw StreamException(); }
}
void EnsureStreamNotFail(const std::ios& s)
{
if (s.fail()) { throw StreamException(); }
}
I test them immediately before and after performing stream operations if I don't expect a failure.
Traditionally in C++, stream operations don't throw exceptions. This is partly for historic reasons, and partly because streaming failures are expected errors. The way C++ standard stream classes deal with this is to set a flag on a stream to indicate an error has occurred, which user code can check. Not using exceptions makes resumption (which is often required for streaming ops) easier than if exceptions were thrown.
I'm developing a C api for some functionality written in C++ and I want to make sure that no exceptions are propagated out of any of the exported C functions.
The simple way to do it is making sure each exported function is contained in a:
try {
// Do the actual code
} catch (...) {
return ERROR_UNHANDLED_EXCEPTION;
}
Let's say I know one exception that is often missed inside the C++ code is std::bad_alloc and I want to treat it specially I'd write something like this instead:
try {
// Run the actual code
} catch (std::bad_alloc& e) {
return ERROR_BAD_ALLOC;
} catch (...) {
return ERROR_UNHANDLED_EXCEPTION;
}
Is it possible to decompose this in some clever way so that I can globally treat some errors differently without adding a new catch statement for the exception handler around every exported function?
I'm aware of that this is possible to solve using the preprocessor, but before going down that road, I'd make sure there is no other way to do it.
You can use only one handler function for all possible exceptions, and call it from each or your API implementation functions, as below:
int HandleException()
{
try
{
throw;
}
// TODO: add more types of exceptions
catch( std::bad_alloc & )
{
return ERROR_BAD_ALLOC;
}
catch( ... )
{
return ERROR_UNHANDLED_EXCEPTION;
}
}
And in each exported function:
try
{
...
}
catch( ... )
{
return HandleException();
}
There already is a good answer. But just FYI, its called 'exception-dispatcher' idiom, see C++ FAQ.
What about:
try{
//Your code here
} catch(std::exception e)
{
return translateExceptionToErrorCode(e);
} catch(...)
{
return UNKNOWN_EXCEPTION_THROWN;
}
Jem answer is a little more simpler than this solution. But it is possible to substitute the use of a preprocessor macro with the use of templates. Something like this (more refinements you could made):
template <class T, void (T::*FUNC)()>
class CatchWrapper
{
public:
static void WrapCall(T* instance)
{
try
{
(instance->*FUNC)();
}
catch (std::bad_alloc&)
{
// Do Something 1
}
catch (std::exception& e)
{
// Do Something 2
}
catch (...)
{
// Do Something 3
}
}
};
class Foo
{
public:
void SomeCall()
{
std::cout << "Do Something" << std::endl;
}
};
int main(int argc, char* argv[])
{
Foo i;
CatchWrapper<Foo, &Foo::SomeCall>::WrapCall(&i);
return 0;
}
Do not ever use catch(...), unless you plan on more or less immediately re-throwing. You will certainly lost any error information you might have had to help you figure out the cause of the error.
I like your second scheme a little better - catch a known set of exceptions, ideally because they are the only ones your code will throw, and let the rest through - allowing the app to crash is possibly the best thing to do since you have invoked unknown behaviour it is best to "crash responsibly".
It would be a shame to loose error information at the language boundary. You really should try to translate all exceptions into an error code usable from C.
How you do it really depends on what your exception classes look like. If you control your exception class hierarchy, you can ensure that each class provides a translation using a virtual method. If not, you may still find it practical to use a translator function and test the types of the 'std::exception'-derived exception it receives to translate it into an error code, much like Jem suggested (remember: thrown exceptions will hurt performance anyway, so don't worry about the translation being slow).