A note on the the link you posted; the OP was asking a hypothetical question in regards to what happens ('under the hood') to the call stack/exception/etc. if the exception that is caught is of a reference type (i.e. catch (std::exception& e)
vs catch (const std::exception& e)
). As was answered there, yes it is not a good idea to modify the exception within a catch (though completely legal code, still not advised).
Per your code, there are a couple of things worth noting:
Changing your err
type from a std::array<char, long_enough>
to a std::string
would simplify all of your code, also, don't pass const char[]
into functions, pass a pointer instead const char*
, passing a char[]
could cause stack issues, also, if you're working with C++, unless you have a specific need to use a char[]
use a std::string
; note that if you're intent WAS to pass in a reference to a char[]
, it's recommended you pass a const size template<int N> someFn(const char (&x)[N])
. Lastly, while having an append
function to add aditional information into your exception object could be useful, it's usually better to derive a specific exception from your base exception with specific information in it (or otherwise just put the needed information in your throw exception...
). Here's you're exception class with the err
variable being a std::string
class my_exception : virtual public std::exception {
private:
std::string err;
public:
void append(std::string::iterator first, std::string::iterator last) {
err.append(first, last);
}
void append(const char* msg) {
err.append(msg);
}
my_exception(const char* msg) noexcept : err(msg) {}
virtual const char* what() const throw() {
return err.c_str();
}
};
Use it like such:
try {
throw my_exception("here's a simple message");
} catch (std::exception e) {
e.append("...added some text");
std::cout << "error: " << e.what() << std::endl;
// or printf("error: %s\n", e.what()) for your C friends
}
As a side note (and for reference), here is the exception code from part of an open source framework I'm working on (just in a single header file exception.hpp):
#include <iostream>
#include <exception>
#include <string>
namespace your_namespace {
class exception : virtual public std::exception {
public:
exception() throw() : m_what("general exception") {}
exception(const char *reason) throw() : m_what(reason) {}
exception(const std::string& reason) throw() : m_what(reason) {}
virtual ~exception() throw() {}
virtual const char* what() const throw() { return m_what.c_str(); }
virtual void seterr(const char *err) { this->m_what = std::string(err); }
virtual void seterr(const std::string &err) { this->m_what = err; }
friend std::ostream& operator<<(std::ostream& s, const omni::exception& e)
{ s << e.m_what; return s; }
friend std::basic_ostream<wchar_t>& operator<<(std::basic_ostream<wchar_t>& s, const omni::exception& e) {
s << e.m_what.c_str();
return s;
}
protected:
std::string m_what;
};
class some_other_exception : public your_namespace::exception {
public:
some_other_exception() : exception("some other exception happened") {}
};
}
To use:
try {
throw your_namespace::exception();
} catch (std::exception e) { // or const std::exception&
std::cout << "error: " << e << std::endl;
// or printf("error: %s\n", e.what()) for your C friends
}
try {
throw your_namespace::exception("Here's an exception for you");
} catch (std::exception e) {
std::cout << "error: " << e << std::endl;
}
try {
throw your_namespace::some_other_exception();
} catch (std::exception e) {
std::cout << "error: " << e << std::endl;
}
I hope that can help