一个隐含的try {}抓住main

在我的每个主要function中,我想捕捉某些类别的exception并将其转换为退出代码。

是否有一个更优雅的解决scheme,比开始和结束每个主要function的macros将粘贴隐含的try {} catch我想要的?

我可以通过std::set_terminatefunction实现吗?

例:

 int main(){ try { //<- insert this /* the business logic goes here */ //-> and insert this } catch(const Someclass1& e){ return 2; } catch(const Someclass2& e){ return 3; } //... catch(...){ return 1; } } 

一个干净的方式涉及到使用翻译功能与您的所有异常样板,返回相应的异常退出值。

 template <typename Callable> int call_and_translate_for_boundary(Callable&& func) try { func(); return 0; } catch(const Someclass1& e){ return 2; } catch(const Someclass2& e){ return 3; } //... catch(...){ return 1; } 

在你自己的代码中,你只关心用lambda封装你的业务逻辑,并将其传递给翻译函数,以便它可以捕获和翻译。

 int main() { return call_and_translate_for_boundary([&]{ //business logic here }); } 

我想你可以用宏来做一些事情。 就是这样:

 #define MY_MAIN int main(int argc, char** argv) try // <- yes, try here #define MY_CATCH catch (const Someclass1& e){ return 1; } \ catch (const Someclass2& e){ return 1; } \ ... \ catch (...) { return -1; } MY_MAIN { // usual business... return 0; } MY_CATCH 

这个想法是让宏写一个“围绕”主函数体,这是合法的。

 int main() try { throw 1; } catch (int i) { return 0; } 

活着的小例子

我通常这样做:

 int main2(); int main() try { return main2(); } catch(std::exception &e) { // some display... } 

当然,你可以有更多的捕鱼人员。


如果你需要在多个入口点放置相同的catch处理程序列表,那将是一个不同的问题。 解决方案有catch(...) { foo(); } catch(...) { foo(); } ,其中foo()函数try { throw; } 接着是所有的catch处理程序。

我怀疑如此。 在终止被调用的时候,你已经失去了所有的异常信息(更确切地说,你从来没有这样做 – 当没有可用的处理程序并且在调用地点做出决定时,终止被调用)。 如果没有适用于此的处理程序,则甚至不会创建异常对象。

我熟悉的最干净的解决方案如下所示:

 void standard_exception_handler(); try { whatever(); } catch (...) { standard_exception_handler(); } void standard_exception_handler() { try { throw; // a bare throw preserves the original exception information } catch (const std::exception& ex) { ... } catch (const other_exception& ex) { ... } } 

为了在公共处理程序之外拥有处理程序,您需要让公共处理程序在已知类型上运行(例如,更改catch (...)catch (const my_exception& ex) ,并在通用处理程序中进行必要的更改),或者使用嵌套的try块:

 try { try { whatever(); } catch (...) { standard_exception_handler(); } } catch (const who_knows& ex) { // log and exit } 

我可以改进它,但是我想我可以

  • 玩终止处理程序中的rethrow-catch( 实际上std::terminate是用来打印std::exceptionwhat():行 )
  • 从外面设置终止处理程序,所以main根本不知道它

有了这个,我的main不必“知道”这个异常到出口代码的翻译,这是我的目标:

 #include <stdexcept> #include <cstdlib> struct Someclass1 {}; struct Someclass2 {}; bool hasDefaultExceptionHandler = (std::set_terminate([](){ try { throw; } catch(const Someclass1& e){ exit(2); } catch(const Someclass2& e){ exit(3); } catch(...){ exit(1); } }), true); // Main has no idea int main(){ throw Someclass2{}; } //will exit with 3 

感谢大家的好主意。