我可以写一个类似于简化函数模板的catch子句吗?

Can I write a catch clause similar to abbreviated function templates?

本文关键字:函数模板 catch 子句 类似于 一个 我可以      更新时间:2023-10-16

在程序的顶部,我有一个异常处理程序。
它看起来像这样:

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
}

Coliru

换句话说,down const&参数将接受可转换为down的任何,而down const&处理程序将绑定到类型为down的异常对象或从down中明确公开派生的类型。

这里最大的区别是形式"可转换为"的关系可以有多种形式。在我们的示例中,我们使用了转换构造函数,但是我们可以在up内部使用转换操作符。而'is(公开的,明确的)派生自'只能以一种直接的方式被选中,并且只能在程序范围内的一个位置:定义派生类型的地方。当我们考虑单独编译时,这一点很重要。考虑下面的程序:

// 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使表达式有意义,那么在哪里,何时以及如何记录?请注意modelother是如何分别定义的,并且每个都不了解对方(太多)。

当然,你所要求的并非完全不可能,但我希望我们能同意它看起来与我们现有的系统完全不同,需要付出很多努力才能奏效。在目前的规则下,异常的泛型编程只能到此为止,使用老式的类层次结构是阻力最小的途径。