针对C++;20份合同(断言) 萨特给出了C++中异常的未来和即将出现的合同,以取代或增强现有的.

针对C++;20份合同(断言) 萨特给出了C++中异常的未来和即将出现的合同,以取代或增强现有的.,c++,contract,c++20,C++,Contract,C++20,他假设以下规则来处理错误处理: 系统损坏(例如堆栈溢出):终止 编程错误(例如,违反先决条件):断言、契约 可恢复错误(如网络故障):异常、错误代码 虽然我同意,但我并没有使用这种方法,而是将2和3组合成一个。我这样做是因为我不知道如何测试断言或即将到来的契约。两者都使用类似的机制,即它们的冲突导致程序终止,并在此之前调用可选的处理程序 从(重点是我的): 一个程序可以使用以下两种模式之一进行翻译: 关闭(如果未选择继续模式,则默认):执行后 当违规处理程序完成时,调用std::term

他假设以下规则来处理错误处理:

  • 系统损坏(例如堆栈溢出):终止

  • 编程错误(例如,违反先决条件):断言、契约

  • 可恢复错误(如网络故障):异常、错误代码

  • 虽然我同意,但我并没有使用这种方法,而是将23组合成一个。我这样做是因为我不知道如何测试断言或即将到来的契约。两者都使用类似的机制,即它们的冲突导致程序终止,并在此之前调用可选的处理程序

    从(重点是我的):

    一个程序可以使用以下两种模式之一进行翻译:

    • 关闭(如果未选择继续模式,则默认):执行后 当违规处理程序完成时,调用std::terminate
    • on:在冲突处理程序的执行完成后,执行 正常继续
    鼓励实施不提供任何 以编程方式查询、设置或修改生成级别或设置或修改 修改违规处理程序。

    这意味着将根据合同测试的测试程序将需要额外的编译开关。虽然我不喜欢这样,但我明白为什么会这样做。更令人担忧的是最后一部分,以及关于它的问题。如果设置我们自己的契约冲突处理程序的能力是由实现定义的,那么它在工具链中就不一致。因此,如果可能的话,合同的任何测试都是不可移植的。将它设置为链接器的另一个参数也会非常尴尬(而且绝对不可移植)

    目前,针对
    assert
    进行测试是不可能的,因为它只会中止程序,而据我所知,自定义处理程序无法阻止这一点。对于契约,使用自定义处理程序和build开关应该可以做到这一点,但事实证明,这可能也不可能(或者是由实现定义的)


    或者有没有其他可能我遗漏的针对资产和合同的测试方法?

    在合同违反方面,实施差异不大。“”确定是否进行合同检查。将对任何失败的已检查契约调用违规处理程序

    处理程序的原型由规范定义。关于违规处理程序的唯一实现差异是如何设置它。注意,“实现定义”并不意味着“不允许这种情况发生”。也就是说,这个机制将与实现一起记录(这就是“实现定义”的含义,而不仅仅是“未指定”)。具体是什么机制将取决于实现,但不提供机制不是一种选择

    唯一可能出现的真正问题是,如果多个实现决定允许用户通过指定特定的全局名称来指定处理程序,并且这些实现是否使用不同的全局名称。然而,由于许多原因(与现有代码、宏等冲突),选择全局名称是一个坏主意,因此在现实中不太可能出现问题。因此,他们很可能会选择明显的机制:一个编译器开关,指定要用作处理程序的函数的名称

    请注意,使处理程序定义为静态而不是定义为运行时的原因之一是确保该开关是编译器开关而不是链接器开关。毕竟,编译器是发出任何概念检查代码的编译器。因此,编译器可以在所述检查代码中使用所述函数的名称


    当然,不同的编译器可能会有不同的编译器开关来确定调用哪个函数。但是他们已经有了不同的开关来生成调试信息、优化级别,以及基本上所有其他的东西。因此,无论您使用什么样的跨平台测试系统,都需要能够处理这些差异。违规处理程序只是多了一个。

    “目前无法对assert进行测试,因为它只是中止程序,而据我所知,自定义处理程序无法阻止。”在讨论合同时,他们通常谈论的是合同
    [[assert:]
    ,不是宏
    assert
    @nicolabolas当然是的,但问题基本相同。不同之处在于,在调用处理程序时,将有一个关闭中止的选项。但若自定义处理程序不被允许,那个么就无法检查它是否被调用(违反了合同)。