5

At the top of my program, I have an exception handler.
It looks something like this:

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(){
    //...
}

As I obtain more an more exception types,
I'd like to take a more generic approach.
How can I apply generic programming to the Handle_All_Exceptions function?


Would something like this be possible in newer versions of C++?

catch(auto e){Handle(e)};
catch(...){Handle_Unknown();}
4

1 回答 1

0

如果不对语言及其异常系统进行重大更改,这是不可能的。虽然 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。而“是(公开地,明确地)派生自”只能以一种直接的方式选择加入,并且只能在程序范围内的一个位置选择:定义派生类型的任何地方。当我们考虑单独编译时,这一点很重要。考虑以下程序:

// 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是如何单独定义的,并且每个人都不太了解对方。

当然,您所要求的并非不可能,但我希望我们能同意它与我们现在拥有的系统看起来完全不同,并且需要付出很多努力才能发挥作用。在当前规则下,异常的通用编程只能走这么远,使用老式的类层次结构是阻力最小的路径。

于 2015-09-13T17:54:23.863 回答