c++ - 针对 C++20 契约(断言)进行测试

标签 c++ contract c++20

Herb Sutter 发表了一份关于 C++ 中异常的 future 以及即将取代或增强现有 talk at ACUU Conference 的合约的 assert

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

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

  2. 编程错误(例如违反前提条件):断言、契约

  3. 可恢复的错误(例如,网络中断):异常、错误代码

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

来自 documentation(重点是我的):

A program may be translated with one of two violation continuation modes:

  • off (default if no continuation mode is selected): after the execution of the violation handler completes, std::terminate is called;
  • on: after the execution of the violation handler completes, execution continues normally.

Implementations are encouraged to not provide any programmatic way to query, set, or modify the build level or to set or modify the violation handler.

这意味着将根据契约(Contract)进行测试的测试程序将需要额外的编译开关。虽然我不喜欢这样,但我理解为什么要这样做。更令人担心的是最后一部分,以及关于它的问题 has been raised 。如果设置我们自己的契约(Contract)违规处理程序的能力是实现定义的,那么跨工具链将不一致。因此,如果可能的话,契约(Contract)的任何测试都将不可移植。将它设置为链接器的另一个参数也会很尴尬(而且绝对不可移植)。

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

或者是否有任何其他方法可以针对我遗漏的断言和契约(Contract)进行测试?

最佳答案

在违反契约(Contract)方面没有太大的实现差异。 “build level” 确定契约(Contract)检查是否完全发生。违规处理程序将针对任何失败的已检查合约调用。

处理程序的原型(prototype)由规范定义。关于违规处理程序的唯一实现差异是您如何设置它。请注意,“实现定义”并不意味着“不允许这种情况发生”。即 the standard says that there will be a mechanism to establish the handler ,并且此机制与实现一起记录(这就是“实现定义”的意思,而不仅仅是“未指定”)。该机制究竟是什么将取决于实现,但不提供一个不是一个选项。

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

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

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

关于c++ - 针对 C++20 契约(断言)进行测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55964700/

相关文章:

c++ - 从复杂(嵌套)mpl 序列转换而来的 boost::fusion::result_of::as_set(或 as_vector)

c++ - Qt 没有匹配函数供调用

c++ - `inline` 和 `noexcept` 在 consteval 上下文中是多余的吗?

C++ 如何忽略头文件中定义的方法?

c++ - 从函数指针的 std::array 调用函数

java - Maven 构建中的契约(Contract)检查

c++ - 推导可调用参数类型时如何指定C++可调用概念

c++ - 您如何逆转strong_ordering?

function - Racket : expected: procedure?

class - 接口(interface)契约,类对象?