在我的程序的顶部,我有一个异常处理程序。
它看起来像这样:
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(){
//...
}
随着我获得更多异常类型,
我想采用更通用的方法。
如何将泛型编程应用于 Handle_All_Exceptions
函数?
在较新版本的 C++ 中是否可以实现类似的功能?
catch(auto e){Handle(e)};
catch(...){Handle_Unknown();}
最佳答案
如果不对语言及其异常系统进行重大更改,这是不可能的。虽然 catch 子句处理程序和函数参数在语法上看起来相似,但它们的工作方式却大不相同。考虑:
struct up {};
struct down { constexpr down(up) noexcept {} };
void func(down const&) {}
void except()
{
try {
throw up {};
} catch(down const&) {}
}
int main()
{
func(up {}); // fine
except(); // exception `up` escapes
}
换句话说,down const&
参数将接受任何可转换为down
的参数,而down const&
处理程序将绑定(bind)到 down
类型的异常对象或明确地公开派生 down
类型的异常对象。
这里最大的区别在于“可转换为”形式的关系可以采用多种形式。在我们的示例中,我们使用了转换构造函数,但我们可以在 up
中使用转换运算符。而“是(公开地,明确地)派生自”只能以一种直接的方式选择加入,并且只能在程序范围内的一个位置:定义派生类型的任何地方。当我们考虑单独编译时,这一点很重要。考虑以下程序:
// a.cpp
// defined in b.cpp
void throws() noexcept(false);
template<typename X>
concept bool Fooable = requires(X x) { x.foo(); }
int main()
{
try {
throws();
// imaginary syntax for catching models of a concept
} catch(Fooable const&) {}
}
// b.cpp
// defined in c.cpp
struct other;
struct model {
void foo() {}
other* foo(int) { return nullptr; }
void bar() {}
};
void throws() noexcept(false)
{ throw model {}; }
// c.cpp omitted
当 b.cpp
被编译时,编译器无法知道 a.cpp
会问这样的问题“你抛出的那个对象是否能够x.foo()
?'。尽管如此,它是否应该悲观地记录这个事实(在当前规则下以同样的方式“是从”关系(如果有的话)记录在某处)?它是否还应该记录 model
能够执行 x.bar()
的事实,即使整个程序不需要它?如果 Fooable
改为测试 x.foo(0)->baz()
会怎么样?如果定义了 other
使得表达式有意义,那么在哪里、何时以及如何记录?请注意 model
和 other
是如何分别定义的,并且彼此之间(了解不多)。
当然,您的要求并非完全不可能,但我希望我们能同意它看起来与我们现在拥有的系统完全不同,并且需要付出很多努力才能发挥作用。根据当前规则,针对异常的泛型编程只能走这么远,使用老式的类层次结构是阻力最小的途径。
关于c++ - 我可以写一个类似于缩写函数模板的 catch 子句吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32527343/