#include <iostream>
#include <array>
#include <algorithm>
#include <cstring>
using namespace std;
const unsigned int long_enough = 512;
class my_exception : public exception {
std::array<char, long_enough> err;
std::array<char, long_enough>::iterator insertion_point;
public:
template <typename Iter>
void append(Iter first, Iter last) noexcept {
//Remember null terminator!
auto space_left = std::distance(insertion_point, err.end());
if (std::distance(first, last)>=space_left){
last = first + (space_left - 1);
}
insertion_point = copy(first, last, insertion_point); //TODO: bounds, start
}
void append(const char msg[]) noexcept {
append(msg, msg+strlen(msg));
}
my_exception(const char msg[]) noexcept {
insertion_point = err.begin();
append(msg, msg+strlen(msg));
}
virtual const char* what() const noexcept override{
return err.data();
}
};
void i_will_throw() {
throw my_exception("i_will_throw: demonstrating exception propagation mechanism");
}
void i_will_rethrow() {
try {
i_will_throw();
} catch (my_exception& e) {
e.append("\n<<--via: i_will_rethrow");
throw;
}
}
void recurse_and_throw(char how_deep) {
std::string name_with_depth = "\n<<--via: recurse_and_throw(";
name_with_depth += how_deep; name_with_depth += ")";
try {
if (how_deep!='A') {
recurse_and_throw(how_deep - 1);
} else {
i_will_throw();
return;
}
} catch (my_exception& e) {
e.append(name_with_depth.begin(), name_with_depth.end());
throw;
}
}
int main() {
cout << "-------Simple--------" << endl;
try {
i_will_throw();
} catch (exception& e) {
cout << e.what()<<endl;
}
cout << "--------Rethrown-------" << endl;
try {
i_will_rethrow();
} catch (exception& e) {
cout << e.what()<<endl;
}
cout << "--------Recursive-------" << endl;
try {
recurse_and_throw('F');
} catch (exception& e) {
cout << e.what()<<endl;
}
cout << "--------Recursive long-------" << endl;
try {
recurse_and_throw('U');
} catch (exception& e) {
cout << e.what() <<endl;
}
return 0;
}