C++ 围绕main的隐式try{}catch

C++ 围绕main的隐式try{}catch,c++,linux,c++11,C++,Linux,C++11,在我的每个主要函数中,我都希望捕获某些类的异常,并将它们转换为退出代码 有没有比用宏启动和结束每个主函数更优雅的解决方案,这些宏将粘贴我想要的隐式try{}catch 我可以通过std::set\u terminate功能以某种方式实现这一点吗 例如: int main(){ try { //<- insert this /* the business logic goes here */ //-> and insert this

在我的每个主要函数中,我都希望捕获某些类的异常,并将它们转换为退出代码

有没有比用宏启动和结束每个主函数更优雅的解决方案,这些宏将粘贴我想要的隐式
try{}catch

我可以通过
std::set\u terminate
功能以某种方式实现这一点吗

例如:

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; } 
}
intmain(){
请尝试{//并插入此项
}
catch(const Someclass1&e){return 2;}
catch(const Someclass2&e){return 3;}
//...
catch(…){return 1;}
}

我对此表示怀疑。在调用terminate时,您已经丢失了所有异常信息(更准确地说,您从未拥有过它-当没有可用的处理程序时,会调用terminate,然后在调用站点进行确定)。当没有合适的处理程序时,甚至不会创建异常对象。

如果您愿意,我想您可以用宏来做一些事情。以下是方法:

#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 main2();

int main() try {
    return main2();
} catch(std::exception &e)
{ 
    // some display...
}
当然,您可以有更多的捕获处理程序


如果您需要在多个入口点中放置相同的catch处理程序列表,那将是一个不同的问题。这里的解决方案是使用
catch(…){foo();}
,其中
foo()
函数执行
try{throw;}
,然后是所有catch处理程序。

A涉及在所有异常样板中使用转换函数,该函数返回相应异常的退出值

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; } 
我熟悉的模型看起来像:

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 ()
  • 从外部设置终止处理程序,使
    main
    完全不知道它
这样,我的
main
s就不必“知道”exitcode翻译的这个异常,这是我的目标:

#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
#包括
#包括
结构Someclass1{};
结构Someclass2{};
bool hasDefaultExceptionHandler=(std::set_terminate([])){
试试{throw;}
捕获(const Someclass1&e){exit(2);}
catch(const Someclass2&e){exit(3);}
catch(…){exit(1);}
}),对);
//梅因不知道
int main(){
抛出一些class2{};
}//将以3退出


感谢大家的好主意。

您的所有异常是否都与继承相关(或者可能是吗?)@quamrana是的。实际上,它可能只是一个虚拟基类。然后,您可以让每个异常类嵌入返回代码,然后在
main()
中使用一个try/catch来提取并返回它。我首选的方法是避免使用宏:@maxlybert your是迄今为止我见过的最好的解决方案。它值得回答,而不是评论。
try {
    try {
        whatever();
    }
    catch (...)
    {
        standard_exception_handler();
    }
}
catch (const who_knows& ex)
{
    // log and exit
}
#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