Tre*_*key 5 c++ templates try-catch c++-concepts c++17
在我的程序的顶部,我有一个异常处理程序.
它看起来像这样:
try{
//majority of program
}
catch(...){
Handle_All_Exceptions();
}
void Handle_All_Exceptions(){
try{throw;}
catch(TypeA const& e){Handle(e) ;}
catch(TypeB const& e){Handle(e) ;}
catch(TypeC const& e){Handle(e) ;}
catch(TypeD const& e){Handle(e) ;}
catch(...) {Handle_Unknown();}
}
void Handle(TypeA const& e){
//...
}
void Handle(TypeB const& e){
//...
}
void Handle(TypeC const& e){
//...
}
void Handle(TypeD const& e){
//...
}
void Handle_Unknown(){
//...
}
Run Code Online (Sandbox Code Playgroud)
随着我获得更多的异常类型,
我想采用更通用的方法.
如何将泛型编程应用于该 Handle_All_Exceptions 函数?
在较新版本的C++中,这样的事情会有可能吗?
catch(auto e){Handle(e)};
catch(...){Handle_Unknown();}
Run Code Online (Sandbox Code Playgroud)
如果不对语言及其异常系统进行重大更改,这是不可能的。虽然 catch 子句处理程序和函数参数在语法上可能看起来相似,但它们的工作方式却截然不同。考虑:
\n\nstruct up {};\nstruct down { constexpr down(up) noexcept {} };\n\nvoid func(down const&) {}\nvoid except()\n{\n try {\n throw up {};\n } catch(down const&) {}\n}\n\nint main()\n{\n func(up {}); // fine\n except(); // exception `up` escapes\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n换句话说,down const&参数将接受任何可转换为 的内容down,而down const&处理程序将绑定到类型down或明确从公开派生的down类型的异常对象。
这里最大的区别是“可转换为”形式的关系可以采取多种形式。在我们的示例中,我们使用了转换构造函数,但我们也可以在 中使用转换运算符up。而“是(公开地、明确地)派生自”只能以一种直接的方式选择加入,并且只能在程序范围内的一个位置:定义派生类型的任何位置。当我们考虑单独编译时,这一点很重要。考虑以下程序:
// a.cpp\n\n// defined in b.cpp\nvoid throws() noexcept(false);\n\ntemplate<typename X>\nconcept bool Fooable = requires(X x) { x.foo(); }\n\nint main()\n{\n try {\n throws();\n\n // imaginary syntax for catching models of a concept\n } catch(Fooable const&) {}\n}\n\n// b.cpp\n\n// defined in c.cpp\nstruct other;\n\nstruct model {\n void foo() {}\n other* foo(int) { return nullptr; }\n void bar() {}\n};\n\nvoid throws() noexcept(false)\n{ throw model {}; }\n\n// c.cpp omitted\nRun Code Online (Sandbox Code Playgroud)\n\n编译时b.cpp,编译器无法知道a.cpp会问“你\xe2\x80\x99re 抛出的那个对象是否具有能力x.foo()?”。尽管如此,它是否应该悲观地记录该事实(以同样的方式,在当前规则下,“源自”关系,如果有的话,被记录在某处)?即使完整的程序不需要\xe2\x80\x99t,它还应该记录model能够执行的事实吗?x.bar()如果Fooable改为测试怎么办x.foo(0)->baz()?other如果定义得使得表达式有意义,那么将在哪里、何时以及如何记录?model请注意和是如何other单独定义的,并且每个人都不了解对方(很多)。
当然,您所要求的并非完全不可能,但我希望我们能够同意它看起来与我们现在拥有的系统完全不同,并且需要付出很多努力才能发挥作用。根据当前规则,异常的泛型编程只能走到这一步,使用老式的类层次结构是阻力最小的路径。
\n