I am trying to throw a std::exception from managed code so that it is caught in unmanaged code. Where I'm struggling is passing a string (describing the exception) so that the (re-)caught exception can be examined using the what() method ...
#pragma managed
static std::string InvokeMethod() {
try {
//...
}
catch (Exception^ ex) {
std::string myExMsg = msclr::interop::marshal_as<std::string>(ex->ToString());
throw std::exception(myExMsg);
}
}
#pragma unmanaged
void Execute() {
try {
myMethod = InvokeMethod();
}
catch (std::exception ex) {
SetError(ex.what());
}
}
This doesn't compile with "no instance of constructor "stdext:exceptipon::exception" matches the argument list argument types are (std::string)" BUT if I 'hard code' a string into std::exception like this ...
throw std::exception("An error has occurred");
... then that string gets passed along and returned by ex.what(). I also tried ...
throw std::runtime_error(myExMsg);
... but ex.what() just returns a string ending with '\x7F' (in case that's a clue).
It looks to me that std::exception is expecting some other type. But what type? What does 'myExMsg' need to be so that ex.what() returns the same string (that can be used in the SetError method)?
Following suggestion made by #Joe, I inherit from std::exception ...
class InvokeException : public std::exception {
public:
InvokeException(std::string const& message) : msg_(message) { }
virtual char const* what() const noexcept { return msg_.c_str(); }
private:
std::string msg_;
};
... and then ...
const std::string myExMsg = msclr::interop::marshal_as<std::string>(ex->Message);
throw InvokeException(myExMsg);
This is going to go out of scope so I can't use it.
try
{
SomeClass someObject({});
}
catch (std::exception & e)
{
}
someObject(x); // someObject does not exist because it goes out of scope
Here's a useful application of std::optional.
std::optional<SomeClass> maybe_someobject;
try {
maybe_someobject.emplace( /* Constructor parameters go here */);
} catch (... /* or something specific */)
{
/* catch exceptions */
return; // Do not pass "Go". Do not collect $200.
}
SomeClass &someobject=maybe_someobject.value();
// Use someobject normally, at this point. Existing code will have to look
// very hard to be able to tell the difference.
This adds a little bit overhead, but it's quite minimal, but you preserve complete type and RAII-safety.
Construct the object dynamically, eg:
SomeClass *someObject = nullptr;
try
{
someObject = new SomeClass(...);
}
catch (const std::exception &e)
{
}
// or:
// SomeClass *someObject = new(nothrow) SomeClass(...);
if (someObject)
{
// use someObject as needed...
delete someObject;
}
Alternatively:
std::unique_ptr<SomeClass> someObject;
try
{
someObject.reset(new SomeClass(...));
// or:
// someObject = std::make_unique<SomeClass>(...);
}
catch (const std::exception &e)
{
}
if (someObject)
{
// use someObject as needed...
}
If have some framework that expects callbacks of a type like
void fcn(F& data);
It can handle exceptions of type ExF.
In my callback, I am using some third party library that throws exceptions of type ExL. So my callbacks look like
void fcn1(F& data)
{
try
{
// call library
}
catch(const ExL& ex)
{
ExF exf = make_ExF(ex);
throw exf;
}
}
Now I want to write more callbacks fcn2, fcn3, ... that use the library but do not want to repeat the same try/catch all the time. In particular, maybe I will add another
catch(const ExL2& ex)
block in the future for several callbacks. I cannot change the code (in particular the exception types) in the framework and the library. How can I avoid repeating the try/catch blocks?
Take advantage of the fact that while you are in a catch block, you have a "currently handled exception" that you can just throw; again. This allows you to move the logic into another function
void except_translate() {
try
{
throw;
}
catch(const ExL& ex)
{
ExF exf = make_ExF(ex);
throw exf;
}
}
void fcn1(F& data)
{
try
{
// call library
}
catch(...)
{
except_translate();
}
}
This technique is known (for googling purposes) as a Lippincott function. It centralizes the error translation logic into one place, so you can easily extend that one function with another handler and it will translate it for all functions that use this utility.
Write a wrapper that does the translation for you.
template <typename Func, typename ... Args>
decltype(auto) translate(Func func, Args&&... args)
{
try {
return func(std::forward<Args>(args)...);
}
catch(const ExL& ex) {
ExF exf = make_ExF(ex);
throw exf;
}
}
Now you can F data; translate(fcn, data) and it works the same way as fcn1(data).
EDIT above code doesn't work as a callback unless one wraps it further (in a lambda for example). Here's an alternative approach:
template <typename Res, typename ... Args>
auto
translate(Res (&func)(Args...)) ->
std::function<Res(Args...)>
{
try {
return [&](Args&& ... args) { return func(std::forward<Args>(args)...); };
}
catch(const ExL& ex) {
ExF exf = make_ExF(ex);
throw exf;
}
}
Then your callback is translate(fcn).
Both of these are very general, if you only need to wrap one type of callback, here's an easy way:
template<void FCT(F& data)>
void translate(F& data)
{
try {
FCT(data);
}
catch(const ExL& ex) {
ExF exf = make_ExF(ex);
throw exf;
}
}
and the callback is translate<fcn>.
(This is basically the same as your answer but with a standalone function instead of a static member).
This is a solution based on the idea of n.m.:
void fcn1_inner(F& data)
{
// call library, no try/catch
}
template<void FCT(F& data)> struct Wrapper
{
static void FN(F& data)
{
try
{
FCT(data);
}
catch(const ExL& ex)
{
ExF exf = make_ExF(ex);
throw exf;
}
}
};
The callback is now
Wrapper<fcn1_inner>::FN
In my code I use my defined BasicException
enum class MyError {
ERROR_1,
ERROR_2
};
class BasicException
{
public:
BasicException(MyError err): _err(err) {}
get_error() const {return _err;}
private:
MyError _err;
}
The problem is that I was told that BasicException should inherit from std::exception. But then, When I will catch (const std::exception& e) I won't be able to retrieve the MyError of the specific error. So what good is in it?
I'm not sure what will be the optimal solution - But maybe if std::exception had a constructor that receives error value it would solve it.
If you want to specifically catch BasicException, catch it first like this :
try
{
}
catch( BasicException& be )
{
// your exception here
}
catch( std::exception& e )
{
// other exceptions here
}
And if you want to catch all exception including yours ( if BasicException inherit of std::exception ), then :
try
{
}
catch( std::exception& e )
{
// all exceptions here
}
I'm a student in my first C++ programming class, and I'm working on a project where we have to create multiple custom exception classes, and then in one of our event handlers, use a try/catch block to handle them appropriately.
My question is: How do I catch my multiple custom exceptions in my try/catch block? GetMessage() is a custom method in my exception classes that returns the exception explanation as a std::string. Below I've included all the relevant code from my project.
Thanks for your help!
try/catch block
// This is in one of my event handlers, newEnd is a wxTextCtrl
try {
first.ValidateData();
newEndT = first.ComputeEndTime();
*newEnd << newEndT;
}
catch (// don't know what do to here) {
wxMessageBox(_(e.GetMessage()),
_("Something Went Wrong!"),
wxOK | wxICON_INFORMATION, this);;
}
ValidateData() Method
void Time::ValidateData()
{
int startHours, startMins, endHours, endMins;
startHours = startTime / MINUTES_TO_HOURS;
startMins = startTime % MINUTES_TO_HOURS;
endHours = endTime / MINUTES_TO_HOURS;
endMins = endTime % MINUTES_TO_HOURS;
if (!(startHours <= HOURS_MAX && startHours >= HOURS_MIN))
throw new HourOutOfRangeException("Beginning Time Hour Out of Range!");
if (!(endHours <= HOURS_MAX && endHours >= HOURS_MIN))
throw new HourOutOfRangeException("Ending Time Hour Out of Range!");
if (!(startMins <= MINUTE_MAX && startMins >= MINUTE_MIN))
throw new MinuteOutOfRangeException("Starting Time Minute Out of Range!");
if (!(endMins <= MINUTE_MAX && endMins >= MINUTE_MIN))
throw new MinuteOutOfRangeException("Ending Time Minute Out of Range!");
if(!(timeDifference <= P_MAX && timeDifference >= P_MIN))
throw new PercentageOutOfRangeException("Percentage Change Out of Range!");
if (!(startTime < endTime))
throw new StartEndException("Start Time Cannot Be Less Than End Time!");
}
Just one of my custom exception classes, the others have the same structure as this one
class HourOutOfRangeException
{
public:
// param constructor
// initializes message to passed paramater
// preconditions - param will be a string
// postconditions - message will be initialized
// params a string
// no return type
HourOutOfRangeException(string pMessage) : message(pMessage) {}
// GetMessage is getter for var message
// params none
// preconditions - none
// postconditions - none
// returns string
string GetMessage() { return message; }
// destructor
~HourOutOfRangeException() {}
private:
string message;
};
If you have multiple exception types, and assuming there's a hierarchy of exceptions (and all derived publicly from some subclass of std::exception,) start from the most specific and continue to more general:
try
{
// throws something
}
catch ( const MostSpecificException& e )
{
// handle custom exception
}
catch ( const LessSpecificException& e )
{
// handle custom exception
}
catch ( const std::exception& e )
{
// standard exceptions
}
catch ( ... )
{
// everything else
}
On the other hand, if you are interested in just the error message - throw same exception, say std::runtime_error with different messages, and then catch that:
try
{
// code throws some subclass of std::exception
}
catch ( const std::exception& e )
{
std::cerr << "ERROR: " << e.what() << std::endl;
}
Also remember - throw by value, catch by [const] reference.
You should create a base exception class and have all of your specific exceptions derive from it:
class BaseException { };
class HourOutOfRangeException : public BaseException { };
class MinuteOutOfRangeException : public BaseException { };
You can then catch all of them in a single catch block:
catch (const BaseException& e) { }
If you want to be able to call GetMessage, you'll need to either:
place that logic into BaseException, or
make GetMessage a virtual member function in BaseException and override it in each of the derived exception classes.
You might also consider having your exceptions derive from one of the standard library exceptions, like std::runtime_error and use the idiomatic what() member function instead of GetMessage().
Another way to solve this problem when you don't have control on the class hierarchy of the exceptions and that you can't duplicate the contents of the catch block is using dynamic_cast Like this:
try
{
...
}
catch (std::exception& e)
{
if( nullptr == dynamic_cast<exception_type_1*> (&e)
&& nullptr == dynamic_cast<exception_type_2*> (&e))
{
throw;
}
// here you process the expected exception types
}
When templates can't, macros save the day.
The solution is taken from Boost. It boils to 7 lines of code.
/// #file multicatch.hpp
#include <boost/preprocessor/variadic/to_list.hpp>
#include <boost/preprocessor/list/for_each.hpp>
/// Callers must define CATCH_BODY(err) to handle the error,
/// they can redefine the CATCH itself, but it is not as convenient.
#define CATCH(R, _, T) \
catch (T & err) { \
CATCH_BODY(err) \
}
/// Generates catches for multiple exception types
/// with the same error handling body.
#define MULTICATCH(...) \
BOOST_PP_LIST_FOR_EACH(CATCH, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
// end of file multicatch.hpp
/// #file app.cc
#include "multicatch.hpp"
// Contrived example.
/// Supply the error handling logic.
#define CATCH_BODY(err) \
log() << "External failure: " << err.what(); \
throw;
void foo() {
try {
bar(); // May throw three or more sibling or unrelated exceptions.
}
MULTICATCH(IOError, OutOfMemory)
}
#undef CATCH_BODY
Derive all of your exceptions from a common base class BaseException that has a virtual method GetMessage().
Then catch(const BaseException& e).
I had a similar problem today, but it turned out I didn't need my solution to solve my problem. Honestly, I couldn't think of real use cases (logging?), and I didn't find much use for it in my code.
Anyway, this is an approach with type lists (requires C++11). I think the advantage of this approach is that there's no need to have a common base class for custom exceptions (except for std::exception, maybe?). In other words, it is not intrusive to your exception hierarchy.
There might be some subtle errors that I am not aware of.
#include <type_traits>
#include <exception>
/// Helper class to handle multiple specific exception types
/// in cases when inheritance based approach would catch exceptions
/// that are not meant to be caught.
///
/// If the body of exception handling code is the same
/// for several exceptions,
/// these exceptions can be joined into one catch.
///
/// Only message data of the caught exception is provided.
///
/// #tparam T Exception types.
/// #tparam Ts At least one more exception type is required.
template <class T, class... Ts>
class MultiCatch;
/// Terminal case that holds the message.
/// ``void`` needs to be given as terminal explicitly.
template <>
class MultiCatch<void> {
protected:
explicit MultiCatch(const char* err_msg) : msg(err_msg) {}
const char* msg;
};
template <class T, class... Ts>
class MultiCatch : public MultiCatch<Ts...> {
static_assert(std::is_base_of<std::exception, T>::value, "Not an exception");
public:
using MultiCatch<Ts...>::MultiCatch;
/// Implicit conversion from the guest exception.
MultiCatch(const T& error) : MultiCatch<Ts...>(error.what()) {} // NOLINT
/// #returns The message of the original exception.
const char* what() const noexcept {
return MultiCatch<void>::msg;
}
};
/// To avoid explicit ``void`` in the type list.
template <class... Ts>
using OneOf = MultiCatch<Ts..., void>;
/// Contrived example.
void foo() {
try {
bar(); // May throw three or more sibling or unrelated exceptions.
} catch (const OneOf<IOError, OutOfMemory>& err) {
log() << "External failure: " << err.what();
throw; // Throw the original exception.
}
}
I run into the same problem and here is what I ended up with:
std::shared_ptr<MappedImage> MappedImage::get(const std::string & image_dir,
const std::string & name,
const Packet::Checksum & checksum) {
try {
return std::shared_ptr<MappedImage>(images_.at(checksum));
} catch (std::out_of_range) {
} catch (std::bad_weak_ptr) {
}
std::shared_ptr<MappedImage> img =
std::make_shared<MappedImage>(image_dir, name, checksum);
images_[checksum_] = img;
return img;
}
In my case the function returns when it doesn't get an exception. So I don't actually have to do anything inside the catch but can do the work outside the try.
#include <iostream>
void test(int x)`
{
try{
if(x==1)
throw (1);
else if(x==2)
throw (2.0);
}
catch(int a)
{
cout<<"It's Integer";
}
catch(double b)
{
cout<<"it's Double";
}
}
int main(){
cout<<" x=1";
test(1);
cout<<"X=2";
test(2.0);
return 0;
}`