什么是合同(针对C ++ 17提出的合同)? [英] What are contracts (as proposed for C++17)?

查看:105
本文介绍了什么是合同(针对C ++ 17提出的合同)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在思想B. Stroustrup撰写的有关C ++ 17 的文章,并协助了一个简短的介绍他们的话题,但我不确定我是否真的理解它们。



所以我有一些疑问,如果可以用一些例子来说明它们:




  • 合同是对经典 assert()并且应该一起使用吗?


  • 对于软件开发人员而言,实际上简单地约定了哪些合同?这些合同会对我们处理异常的方式产生影响吗?如果是,我们应该如何使用异常和合同?


  • 使用合同是否意味着执行时的开销?我们可以在发布代码上停用它们吗?




来自提案N4415



< blockquote>

可以编写Vector类的索引运算符的前提条件合同:

T&运算符[](size_t i)[[期望:i< size()]];



类似地,ArrayView类的构造函数的后置条件契约可以表示为:
ArrayView(const vector< T>& v)[[确保:data()== v.data()]];


感谢@Keith Thompson评论:


合同没有使其进入C ++ 20 一个新的研究组SG21,已创建。



解决方案

据我所读文件:
http:// www .open-std.org / JTC1 / SC22 / WG21 / docs / papers / 2015 / n4415.pdf



合同做什么 assert 多年来一直尝试以原始方式进行。它们既是文档,又是运行时断言,表明应如何期望调用方调用该函数,以及在函数返回后,调用方可以期望代码处于哪种状态。



这有助于清理实现方面的代码,因为有了合同,我们可以假设一旦执行已经进入函数内部,您的参数处于有效状态(您希望它们处于什么状态)。



后置条件部分可能会更改您处理异常的方式,因为对于合同,您必须确保引发异常不会破坏您的后置条件。这通常意味着您的代码必须是异常安全的,尽管这是否意味着强异常保证或基本保证取决于您的条件。



示例:

类数据; 
类MyVector {
public:
void MyVector :: push_back(Elem e)[[确保:数据!= nullptr]]
{
if(size> =容量)
{
数据* p =数据;
data = nullptr; //仅出于示例原因...
data = new Data [capacity * 2]; //可能引发异常
//将p复制到数据中并删除p
}
//将元素添加到末尾
}
private:
数据*数据;
//其他数据
};

在此示例中,如果 new Data 的构造函数引发异常,则违反了您的后置条件。这意味着您应该更改所有此类代码,以确保您的合同永不违反!



当然,就像 assert ,合同可能包括运行时开销。不过,不同之处在于,由于可以将合同作为函数声明的一部分放置,因此编译器可以进行更好的优化,例如评估调用者站点的条件,甚至在编译时对其进行评估。就像普通的旧断言一样,本文开头部分提到的文档的第1.5节讨论了根据您的构建配置关闭合同的可能性。


I was reading about contracts in Thoughts about C++17 by B. Stroustrup and assisted a small presentation talking about them but I am not sure I have understood them really.

So I have a some interrogations and if it is possible to illustrate them with some examples :

  • Are contracts just a better replacement of the classic assert() and should they be used together ? What contracts really are put in simple terms for a software dev ?

  • Would contracts have an impact on how we handle exceptions ? If yes, how should we use exceptions and contracts ?

  • Would using contracts imply an overhead at execution time ? Will we be allow to deactivate them on release code ?

From the proposal N4415:

A pre-condition contract of the indexing operator of a Vector class could be written:
T& operator[](size_t i) [[expects: i < size()]];

Similarly, a post-condition contract on a constructor of an ArrayView class could be expressed as: ArrayView(const vector<T>& v) [[ensures: data() == v.data()]];

Thanks to @Keith Thompson comment:

Contracts didn't make it into C++20. A new study group, SG21, has been created.

解决方案

As far as I've read from this document: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4415.pdf

Contracts do what assert has been trying to do in a primitive way for years. They're both documentation and a run-time assert of how the caller should be expected to call the function and in what state can the caller expect the code to be after the function has returned. Those are usually known as pre-conditions and post-conditions, or invariants.

This helps clean up code on the implementation side, because with contracts we can assume that once the execution has gone inside your function, your arguments are in valid state (what you expect them to be).

The post-conditions part might change how you handle exceptions, because with contracts you will have to make sure that throwing an exception won't break your post-conditions. This usually means that your code has to be exception safe, though whether that means strong exception guarantee or basic guarantee depends on your conditions.

Example:

class Data;
class MyVector {
public:
    void MyVector::push_back(Elem e) [[ensures: data != nullptr]]
    {
        if(size >= capacity)
        {
            Data* p = data;
            data = nullptr; // Just for the sake of the example...
            data = new Data[capacity*2]; // Might throw an exception
            // Copy p into data and delete p
        }
        // Add the element to the end
    }
private:
     Data* data;
     // other data
};

In this example here, if new or Data's constructor throws an exception, your post-condition is violated. This means that you should change all such code to make sure your Contract is never violated!

Of course, just like assert, contracts might include a run-time overhead. The difference though is that since contracts can be put as part of the function's declaration, the compiler can do better optimizations, such as evaluating the conditions at the caller's site or even evaluate them at compile time. Section 1.5 of the document mentioned at the beginning of this post talks about the possibilities of turning off contracts depending on your build configuration, just like plain old asserts.

这篇关于什么是合同(针对C ++ 17提出的合同)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆