提供对于标准C/C++ 11完善的SEH(结构化异常处理)处理扩展
1、try
2、catch
3、catch-when
4、finally
usage:
using ep::Try;
class exceptionA : public std::exception {
public:
exceptionA(char const* const _Message) :exception(_Message) {}
};
class exceptionB : public exceptionA {
public:
exceptionB(char const* const _Message) :exceptionA(_Message) {}
};
int main()
{
Try([] {
printf("T1: try\n");
}).Finally([] {
printf("T1: finally\n");
}).Invoke();
Try([] {
printf("T2: throw exceptionB\n");
throw exceptionB("123213213213");
}).Catch<exceptionA>([](exceptionA& e) {
printf("T2: catch: exceptionA=%s\n", e.what());
}, [](exceptionA& e) { // when Type AS B
exceptionB* ec = dynamic_cast<exceptionB*>(&e);
printf("T2: catch-when: exceptionA as exceptionB=%p\n", ec);
return NULL != ec;
}).Catch<std::exception>([](std::exception& e) {
printf("T2: catch: exception=%s\n", e.what());
}).Finally([] {
printf("T2: finally");
}).Invoke();
return getchar();
}
impl:
class Try
{
public:
inline Try(const std::function<void()>& block)
: ___try(block) {
if (!block) {
throw std::runtime_error("The block part of the try is not allowed to be Null References");
}
}
inline ~Try() {
___try = NULL;
___catch = NULL;
___finally = NULL;
}
public:
template<typename TException>
inline Try& Catch() const {
return Catch<TException>([](TException& e) {});
}
template<typename TException>
inline Try& Catch(const std::function<void(TException& e)>& block) const {
return Catch<TException>(block, NULL);
}
template<typename TException>
inline Try& Catch(const std::function<void(TException& e)>& block, const std::function<bool(TException& e)>& when) const {
if (!block) {
throw std::runtime_error("The block part of the try-catch is not allowed to be Null References");
}
if (this) {
auto previous = ___catch;
___catch = [block, previous, when](std::exception* e) {
if (previous) {
if (previous(e)) {
return true;
}
}
TException* exception = dynamic_cast<TException*>(e);
if (!exception) {
return false;
}
if (when) {
if (!when(*exception)) {
return false;
}
}
if (block) {
block(*exception);
}
return true;
};
}
return const_cast<Try&>(*this);
}
inline Try& Finally(const std::function<void()>& block) const {
if (this) {
___finally = block;
}
return const_cast<Try&>(*this);
}
inline int Invoke() const {
if (!this) {
return -1;
}
if (!___try) {
return -2;
}
int ec = 0;
std::exception* exception = NULL; // 未处理异常
try {
___try();
}
catch (std::exception& e) {
ec = 1;
exception = (std::exception*)&reinterpret_cast<const char&>(e);
if (___catch) {
if (___catch(exception)) {
exception = NULL;
}
}
}
if (___finally) {
___finally();
}
if (exception) {
throw *exception;
}
return ec;
}
private:
mutable std::function<void()> ___try;
mutable std::function<bool(std::exception*)> ___catch;
mutable std::function<void()> ___finally;
};