【问题标题】:Why is it recommended not to allow querying the contract level for C++20 Contracts?为什么不建议允许查询 C++20 合约的合约级别?
【发布时间】:2019-10-08 05:01:13
【问题描述】:

当前的 C++ 草案在 [dcl.attr.contract.check] p3 中包含:

不应以编程方式设置、修改或查询 翻译单元的构建级别。

我不明白为什么建议不允许查询合同级别。使用当前的assert 宏,可以通过NDEBUG 宏检测断言是否被使用。

查询合约级别在某些情况下很有用,例如:

  • 添加其他变量以跟踪其他状态。
  • 在原子比较交换中转换原子存储以读取值。

建议无法查询构建级别的理由是什么?

【问题讨论】:

  • 查询合约级别可能是个坏主意。如果您这样做,您的代码将依赖于合同级别,因此您将无法通过增加合同级别来测试您的代码。出于同样的原因,合同违规检查中的副作用会导致 UB。
  • 说实话,这部分合同似乎没有那么令人惊讶的混乱。 @Oliv 但是检查和报告当前构建设置是一种常见的做法(例如“调试,32 位,已检查”)。
  • 我不能 100% 确定这是否是理由,但是:合同不仅仅是验证代码的一种方式。他们还在代码中注入假设。换句话说:即使没有执行运行时验证,合约失败也是 UB。让合约或它们周围的代码根据构建级别进行更改会使事情变得一团糟。
  • @Oliv 我同意它应该很少使用,但有时需要有好的资产
  • @Tyker: "添加额外的变量来跟踪额外的状态" 如果这些变量在合约中使用,你不能这样做。即使没有检查合同,表达式本身也是potentially evaluated。这意味着它必须是一个合法的表达式,即使它没有被评估。就像你不能做decltype(variableThatDoesntExist)

标签: c++ c++20


【解决方案1】:

建议实现不要提供这样的查询,因为它会破坏混合检查级别的使用。

就目前而言,在一个检查级别下构建库并将其链接到在另一个检查级别下构建的代码在形式上并没有错。但是,如果代码可以轻松查询可用的检查级别,则可能会破坏此用例。这样的查询可用于影响类型的 ABI 等等。如果库有这样的接口,那么您必须在相同的检查级别下构建消费代码,以便任何标头等都定义相同的 ABI。

是否可以以不影响 ABI 和接口的方式使用此类查询?当然。但是提供测试会让它太容易搞砸了。

就目前而言,您可以让一个库拥有自己的测试,#define,预计将在特定检查级别或类似的检查级别下编译时定义。但是现在这样的定义是您图书馆构建界面的一部分。这只是您的构建文档的一部分;如果人们在检查级别 X 下构建您的库,他们必须提供 #define。并且任何使用在这种情况下构建的库的代码也必须提供该定义。

这是最好的部分:消费代码不必共享您的检查级别。他们必须分享您的define,而不是实际的检查级别。您的定义属于图书馆;检查级别属于用户。

【讨论】:

  • 这似乎是不允许查询合同级别的一个很好的理由,但您是否有暗示这是原因的来源?
猜你喜欢
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-04
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多