Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[CppOnSea] Programming with Contracts in C++20

[CppOnSea] Programming with Contracts in C++20

Design by Contract is a technique to clearly express which parts of a program has which responsibilities. In the case of bugs, contracts can mercilessly point a finger at the part that violated the contract.

Contracts are coming as a language feature in C++20. I will show how they can make your interfaces clearer with regards to use, but also point out pitfalls and oddities in how contracts are handled in C++.

Writing good contracts can be difficult. I intend to give you guidance in how to think when formulating contracts, and how to design your interfaces such that good contracts can be written, because contracts have effects on interface design.

Warning: Parts of the contents are personal opinion.

Björn Fahller

February 05, 2019
Tweet

More Decks by Björn Fahller

Other Decks in Programming

Transcript

  1. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 1/171
    Programming with Contracts in C++20
    Björn Fahller

    View Slide

  2. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 2/171
    What is a contract?
    contract
    noun con· tract | \ˈkän-ˌtrakt \
    Definition of contract
    (Entry 1 of 3)
    1:
    a: binding agreement between two or more persons or parties - especially : one legally enforceable
    // If he breaks the contract, he'll be sued.
    b: a business arrangement for the supply of goods or services at a fixed price
    // make parts on contract
    c: the act of marriage or an agreement to marry
    2: a document describing the terms of a contract
    // Have you signed the contract yet?
    3: the final bid to win a specified number of tricks in bridge
    4: an order or arrangement for a hired assassin to kill someone
    // His enemies put out a contract on him.
    https:////w.merriam-webster.com/dictionary/contract

    View Slide

  3. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 3/171
    What is a contract?
    contract
    noun con· tract | \ˈkän-ˌtrakt \
    Definition of contract
    (Entry 1 of 3)
    1:
    a: binding agreement between two or more persons or parties - especially : one legally enforceable
    // If he breaks the contract, he'll be sued.
    b: a business arrangement for the supply of goods or services at a fixed price
    // make parts on contract
    c: the act of marriage or an agreement to marry
    2: a document describing the terms of a contract
    // Have you signed the contract yet?
    3: the final bid to win a specified number of tricks in bridge
    4: an order or arrangement for a hired assassin to kill someone
    // His enemies put out a contract on him.
    https:////w.merriam-webster.com/dictionary/contract
    In SW design:
    A formalized agreement, regarding
    program correctness, between a
    user and the implementation of
    a component.

    View Slide

  4. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 4/171
    What is a contract?
    contract
    noun con· tract | \ˈkän-ˌtrakt \
    Definition of contract
    (Entry 1 of 3)
    1:
    a: binding agreement between two or more persons or parties - especially : one legally enforceable
    // If he breaks the contract, he'll be sued.
    b: a business arrangement for the supply of goods or services at a fixed price
    // make parts on contract
    c: the act of marriage or an agreement to marry
    2: a document describing the terms of a contract
    // Have you signed the contract yet?
    3: the final bid to win a specified number of tricks in bridge
    4: an order or arrangement for a hired assassin to kill someone
    // His enemies put out a contract on him.
    https:////w.merriam-webster.com/dictionary/contract
    In SW design:
    A formalized agreement, regarding
    program correctness, between a
    user and the implementation of
    a component.

    View Slide

  5. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 5/171
    Contracts

    Object-oriented Software
    Construction
    – Bertrand Meyer - 1988
    – ISBN 978-0136290490

    View Slide

  6. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 6/171

    Preconditions

    Postconditions

    Class invariants
    Contracts

    View Slide

  7. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 7/171
    Ringbuffer example
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  8. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 8/171
    Ringbuffer example
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  9. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 9/171
    Ringbuffer example
    1
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  10. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 10/171
    Ringbuffer example
    1
    2
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  11. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 11/171
    Ringbuffer example
    1
    2
    5
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  12. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 12/171
    Ringbuffer example
    1
    2
    5
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  13. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 13/171
    Ringbuffer example
    2
    5
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  14. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 14/171
    Ringbuffer example
    2
    5
    8
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  15. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 15/171
    Ringbuffer example
    2
    5
    8
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  16. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 16/171
    Ringbuffer example
    5
    8
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  17. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 17/171
    Ringbuffer example
    5
    8
    11
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  18. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 18/171
    Ringbuffer example
    5
    8
    11
    13
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  19. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 19/171
    Ringbuffer example
    5
    8
    11
    13
    15
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  20. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 20/171
    Ringbuffer example
    5
    8
    11
    13
    15
    21
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  21. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 21/171
    Ringbuffer example
    5
    8
    11
    13
    15
    21
    23
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  22. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 22/171
    Ringbuffer example
    5
    8
    11
    13
    15
    21
    23
    24
    ringbuffer b;
    b.push_back(1);
    b.push_back(2);
    b.push_back(5);
    b.pop_front(); // 1
    b.push_back(8);
    b.pop_front(); // 2
    b.push_back(11);
    b.push_back(13);
    b.push_back(15);
    b.push_back(21);
    b.push_back(23);
    b.push_back(24);

    View Slide

  23. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 23/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };

    View Slide

  24. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 24/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:

    View Slide

  25. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 25/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  26. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 26/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.
    A precondition may
    refer to parameter values
    or the objects state,
    or both

    View Slide

  27. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 27/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  28. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 28/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.
    It almost never makes
    sense to have a
    precondition on a
    default constructor!

    View Slide

  29. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 29/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  30. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 30/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.
    Functions that query
    the state of an object
    rarely has any
    preconditions.

    View Slide

  31. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 31/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  32. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 32/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.
    Choose between:
    Define behaviour when
    full, or make not-full
    a precondition.

    View Slide

  33. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 33/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  34. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 34/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  35. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 35/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.
    Choose between:
    Define behaviour when
    empty, or make not-empty
    a precondition.

    View Slide

  36. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 36/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Precondition:
    An obligation that
    the caller must fulfill
    for the program to
    be correct.

    View Slide

  37. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 37/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:

    View Slide

  38. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 38/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  39. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 39/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.
    A postcondition
    may refer to return value
    or the objects state, or both,
    sometimes dependent on
    parameter values

    View Slide

  40. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 40/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  41. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 41/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  42. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 42/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  43. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 43/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    void push_back(T);
    // requires: size() < N
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  44. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 44/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    void push_back(T);
    // requires: size() < N
    // ensures: size() /= old size()+1
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  45. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 45/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  46. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 46/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  47. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 47/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  48. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 48/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.
    What if an exception
    is thrown?

    View Slide

  49. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 49/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.
    Postconditions handles
    return. If an exception is
    thrown, there is no
    post condition.

    View Slide

  50. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 50/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  51. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 51/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  52. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 52/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  53. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 53/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.

    View Slide

  54. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 54/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& top() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Postcondition:
    A guarantee from
    the implementation
    regarding the effect
    of a legal call.
    It does not make sense
    to try and express the returned
    value from the history of pushes
    and pops as a post condition.

    View Slide

  55. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 55/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Class invariant:

    View Slide

  56. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 56/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Class invariant:
    Something that is
    always* true for a
    valid instance
    * outside public API

    View Slide

  57. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 57/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Class invariant:
    Something that is
    always* true for a
    valid instance
    * outside public API
    A class invariant
    always refers to state,
    and must be true even
    when exceptions are
    thrown.

    View Slide

  58. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 58/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Class invariant:
    Something that is
    always* true for a
    valid instance
    * outside public API

    View Slide

  59. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 59/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Class invariant:
    Something that is
    always* true for a
    valid instance
    * outside public API
    What about a
    moved-from
    object?

    View Slide

  60. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 60/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Contracts and
    templates

    View Slide

  61. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 61/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // ensures: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Contracts and
    templates
    What about
    specializations?

    View Slide

  62. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 62/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    virtual int size() const = 0;
    virtual const T& back() const = 0;
    // requires: size() > 0
    virtual const T& front() const = 0;
    // requires: size() > 0
    virtual void push_back(T t) = 0;
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    virtual T pop_front() = 0;
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Contracts and
    inheritance:

    View Slide

  63. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 63/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    virtual int size() const = 0;
    virtual const T& back() const = 0;
    // requires: size() > 0
    virtual const T& front() const = 0;
    // requires: size() > 0
    virtual void push_back(T t) = 0;
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    virtual T pop_front() = 0;
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Contracts and
    inheritance:
    A subcontractor
    may have more
    relaxed pre-
    conditions

    View Slide

  64. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 64/171
    Ringbuffer example
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    virtual int size() const = 0;
    virtual const T& back() const = 0;
    // requires: size() > 0
    virtual const T& front() const = 0;
    // requires: size() > 0
    virtual void push_back(T t) = 0;
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    virtual T pop_front() = 0;
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Contracts and
    inheritance:
    A subcontractor
    may have more
    relaxed pre-
    conditions
    and stricter post-
    conditions

    View Slide

  65. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 65/171
    Why bother?

    View Slide

  66. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 66/171
    Why bother?
    1)It can make interfaces much clearer

    View Slide

  67. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 67/171
    Why bother?
    1)It can make interfaces much clearer
    2)It can make debugging much easier

    View Slide

  68. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 68/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  69. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 69/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant
    Elementary,
    Mr. Watson

    View Slide

  70. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 70/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  71. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 71/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  72. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 72/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  73. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 73/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  74. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 74/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  75. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 75/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant

    View Slide

  76. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 76/171
    Who dunnit?
    guilty
    client implementation
    violation
    precondition
    postcondition
    invariant
    Or you have
    a bad contract!

    View Slide

  77. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 77/171
    Contracts in C++20

    View Slide

  78. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 78/171
    Contracts in C++20

    View Slide

  79. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 79/171
    Contracts in C++20
    Description of
    contract attribute
    declarations and
    semantics here
    (4 pages)

    View Slide

  80. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 80/171
    Contracts in C++20
    Description of
    contract violation
    handlers

    View Slide

  81. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 81/171
    Contracts in C++20
    Meaning for
    virtual functions
    (1 paragraph)

    View Slide

  82. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 82/171
    Contracts in C++20
    Contracts and
    templates
    (1 non-formative
    sentence)

    View Slide

  83. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 83/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1

    View Slide

  84. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 84/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Pre condition

    View Slide

  85. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 85/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Pre condition
    template
    void func(std/:unique_ptr p)
    [[ expects : p /= nullptr ]];

    View Slide

  86. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 86/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Optional level
    template
    void func(std/:unique_ptr p)
    [[ expects : p /= nullptr ]];

    View Slide

  87. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 87/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Optional level
    template
    void func(std/:unique_ptr p)
    [[ expects axiom : p /= nullptr ]];

    View Slide

  88. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 88/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Post condition

    View Slide

  89. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 89/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    template
    T prev(T v)
    [[ expects : v > 0 ]]
    [[ ensures audit r : r + 1 /= v ]];
    Post condition

    View Slide

  90. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 90/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    template
    T prev(T v)
    [[ expects : v > 0 ]]
    [[ ensures audit r : r + 1 /= v ]];
    Name for
    return value
    to use in
    conditional
    expression
    Post condition

    View Slide

  91. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 91/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Generic
    assertion

    View Slide

  92. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 92/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    Generic
    assertion
    for (auto p : pointers) {
    [[ assert axiom: p /= nullptr ]];
    func(p);
    }

    View Slide

  93. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 93/171
    Contract attributes in C++20
    9.11.4.1 Syntax [dcl.attr.contract.syn]
    1# Contract attributes are used to specify preconditions, postconditions, and assertions for functions.
    contract-attribute-specifier:
    [ [ expects contract-level
    opt
    : conditional-expression ] ]
    [ [ ensures contract-level
    opt
    identifier
    opt
    : conditional-expression ] ]
    [ [ assert contract-level
    opt
    : conditional-expression ] ]
    contract-level:
    default
    audit
    axiom
    An ambiguity between a contract-level and an identifier is resolved in favor of contract-level.
    http://eel.is/c/+draft/dcl.attr.contract#syn-1
    There are no
    class invariants!

    View Slide

  94. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 94/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  95. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 95/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  96. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 96/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    No support for
    class invariants,
    so might as well
    leave as comment.

    View Slide

  97. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 97/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer();
    // ensures: size() /= 0
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  98. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 98/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  99. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 99/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() < = N
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    :6:15: error: use of undeclared identifier 'size'
    [[ ensures: size() /= 0 ]];

    View Slide

  100. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 100/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() < = N
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    int size() const;
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    :6:15: error: use of undeclared identifier 'size'
    [[ ensures: size() /= 0 ]];
    Contract attributes are
    declarations that can only
    refer to identifiers seen
    earlier.

    View Slide

  101. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 101/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() < = N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Contract attributes are
    declarations that can only
    refer to identifiers seen
    earlier.

    View Slide

  102. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 102/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const;
    // requires: size() > 0
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  103. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 103/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  104. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 104/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const;
    // requires: size() > 0
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  105. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 105/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  106. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 106/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t);
    // requires: size() < N
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old back();
    };

    View Slide

  107. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 107/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]];
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old back();
    };

    View Slide

  108. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 108/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]];
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  109. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 109/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]];
    // ensures: size() /= old size()+1
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    There is no way
    to refer to previous state
    so this cannot be
    expressed!

    View Slide

  110. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 110/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]]; // incremented
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  111. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 111/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]];
    [[ ensures: size() > 0 ]]; // incremented
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  112. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 112/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]];
    [[ ensures: size() > 0 ]]; // incremented
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    6# If a function has multiple preconditions, their evaluation (if any) will be
    performed in the order they appear lexically. If a function has multiple
    postconditions, their evaluation (if any) will be performed in the order they
    appear lexically. [ Example:
    void f(int * p)
    [[expects: p != nullptr]] // #1
    [[ensures: *p == 1]] // #3
    [[expects: *p == 0]] // #2
    {
    *p = 1;
    }
    — end example ]
    http://eel.is/c/+draft/dcl.attr.contract#cond-6

    View Slide

  113. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 113/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]];
    [[ ensures: size() > 0 ]]; // incremented
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    6# If a function has multiple preconditions, their evaluation (if any) will be
    performed in the order they appear lexically. If a function has multiple
    postconditions, their evaluation (if any) will be performed in the order they
    appear lexically. [ Example:
    void f(int * p)
    [[expects: p != nullptr]] // #1
    [[ensures: *p == 1]] // #3
    [[expects: *p == 0]] // #2
    {
    *p = 1;
    }
    — end example ]
    http://eel.is/c/+draft/dcl.attr.contract#cond-6

    View Slide

  114. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 114/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]]; // incremented
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    7# If a postcondition odr-uses ([basic.def.odr]) a parameter in its predicate
    and the function body makes direct or indirect modifications of the value of
    that parameter, the behavior is undefined. [ Example:
    int f(int x)
    [[ensures r: r == x]]
    {
    return ++x; // undefined behavior
    }
    ...
    http://eel.is/c/+draft/dcl.attr.contract#cond-7

    View Slide

  115. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 115/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]]; // incremented
    // back() /= t
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    7# If a postcondition odr-uses ([basic.def.odr]) a parameter in its predicate
    and the function body makes direct or indirect modifications of the value of
    that parameter, the behavior is undefined. [ Example:
    int f(int x)
    [[ensures r: r == x]]
    {
    return ++x; // undefined behavior
    }
    ...
    http://eel.is/c/+draft/dcl.attr.contract#cond-7
    So the validity
    of the post condition
    declaration depends on
    how the function is
    implemented

    View Slide

  116. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 116/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]] // incremented
    [[ ensures: back() /= t ]];
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };
    Potentially
    dangerous

    View Slide

  117. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 117/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]] // incremented
    [[ ensures: back() /= t ]];
    T pop_front();
    // requires: size() > 0
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  118. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 118/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]] // incremented
    [[ ensures: back() /= t ]];
    T pop_front()
    [[ expects: size() > 0 ]];
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  119. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 119/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]] // incremented
    [[ ensures: back() /= t ]];
    T pop_front()
    [[ expects: size() > 0 ]];
    // ensures: size() /= old size()-1
    // return /= old front();
    };

    View Slide

  120. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 120/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]] // incremented
    [[ ensures: back() /= t ]];
    T pop_front()
    [[ expects: size() > 0 ]]
    [[ ensures: size() < N ]]; // decremented
    // return /= old front();
    };

    View Slide

  121. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 121/171
    Using C++20 contract attributes for ringbuffer
    template
    class ringbuffer {
    public:
    // invariant: size() /= 0 /& size() /= N
    int size() const;
    ringbuffer()
    [[ ensures: size() /= 0 ]];
    const T& back() const
    [[ expects: size() > 0 ]];
    const T& front() const
    [[ expects: size() > 0 ]];
    void push_back(T t)
    [[ expects: size() < N ]]
    [[ ensures: size() > 0 ]] // incremented
    [[ ensures: back() /= t ]];
    T pop_front()
    [[ expects: size() > 0 ]]
    [[ ensures: size() < N ]]; // decremented
    // return /= old front();
    };
    Cannot express
    condition with
    previous state so
    might as well leave
    as comment

    View Slide

  122. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 122/171
    Virtual functions and contracts in C++20

    View Slide

  123. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 123/171
    Virtual functions and contracts in C++20
    If an overriding function specifies contract conditions ([dcl.attr.contract]), it shall
    specify the same list of contract conditions as its overridden functions; no
    diagnostic is required if corresponding conditions will always evaluate to the
    same value. Otherwise, it is considered to have the list of contract conditions
    from one of its overridden functions; ...
    http://eel.is/c/+draft/class.virtual#19

    View Slide

  124. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 124/171
    Virtual functions and contracts in C++20
    If an overriding function specifies contract conditions ([dcl.attr.contract]), it shall
    specify the same list of contract conditions as its overridden functions; no
    diagnostic is required if corresponding conditions will always evaluate to the
    same value. Otherwise, it is considered to have the list of contract conditions
    from one of its overridden functions; ...
    http://eel.is/c/+draft/class.virtual#19

    View Slide

  125. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 125/171
    Virtual functions and contracts in C++20
    If an overriding function specifies contract conditions ([dcl.attr.contract]), it shall
    specify the same list of contract conditions as its overridden functions; no
    diagnostic is required if corresponding conditions will always evaluate to the
    same value. Otherwise, it is considered to have the list of contract conditions
    from one of its overridden functions; ...
    http://eel.is/c/+draft/class.virtual#19

    View Slide

  126. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 126/171
    Function pointers and contracts in C++20

    View Slide

  127. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 127/171
    Function pointers and contracts in C++20
    3 #[ Note: A function pointer cannot include contract conditions. [ Example:
    typedef int (*fpt)(int) [[ensures r: r /= 0]];
    // error: contract condition not on a function declaration
    int g(int x) [[expects: x /= 0]] [[ensures r: r > x]]
    {
    return x+1;
    }
    int (*pf)(int) = g; // OK
    int x = pf(5); // contract conditions of g are checked
    — end example ] — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#cond-3

    View Slide

  128. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 128/171
    Function pointers and contracts in C++20
    3 #[ Note: A function pointer cannot include contract conditions. [ Example:
    typedef int (*fpt)(int) [[ensures r: r /= 0]];
    // error: contract condition not on a function declaration
    int g(int x) [[expects: x /= 0]] [[ensures r: r > x]]
    {
    return x+1;
    }
    int (*pf)(int) = g; // OK
    int x = pf(5); // contract conditions of g are checked
    — end example ] — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#cond-3
    In other words, it is
    the responsibility of a function
    implementation to enforce its
    contracts, not the caller.

    View Slide

  129. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 129/171
    Let’s explore!
    https://github.com/arcosuc3m/clang-contracts
    Fork from clang-6
    http://fragata.arcos.inf.uc3m.es/#

    View Slide

  130. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 130/171
    Function pointers and contracts in C++20
    3 #[ Note: A function pointer cannot include contract conditions. [ Example:
    typedef int (*fpt)(int) [[ensures r: r /= 0]];
    // error: contract condition not on a function declaration
    int g(int x) [[expects: x /= 0]] [[ensures r: r > x]]
    {
    return x+1;
    }
    int (*pf)(int) = g; // OK
    int x = pf(5); // contract conditions of g are checked
    — end example ] — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#cond-3
    P1320R1 Allowing contract predicates on non-first declarations
    Ville Voutilainen
    struct X {
    void f();
    };
    void X/:f() [[expects: foo]]
    {
    //.
    }

    View Slide

  131. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 131/171
    Policing contracts in C++20

    View Slide

  132. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 132/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  133. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 133/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  134. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 134/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  135. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 135/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  136. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 136/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  137. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 137/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3
    P1421r0 Assigning semantics to different Contract Checking Statements
    Andrzej Krzemieński
    Allowing different levels for different types of contracts, e.g. audit on
    preconditions, and off on the others.

    View Slide

  138. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 138/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  139. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 139/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  140. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 140/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3
    3.7 [defns.cond.supp]
    conditionally-supported
    program construct that an implementation is not required to support
    [ Note: Each implementation documents all conditionally-supported
    constructs that it does not support. — end note ]
    http://eel.is/c/+draft/intro.defs#defns.cond.supp

    View Slide

  141. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 141/171
    Policing contracts in C++20
    3# A translation may be performed with one of the following build levels: off,
    default, or audit. A translation with build level set to off performs no checking
    for any contract. A translation with build level set to default performs checking
    for default contracts. A translation with build level set to audit performs
    checking for default and audit contracts. If no build level is explicitly selected,
    the build level is default. The mechanism for selecting the build level is
    implementation-defined. The translation of a program consisting of translation
    units where the build level is not the same in all translation units is conditionally-
    supported. There should be no programmatic way of setting, modifying, or
    querying the build level of a translation unit.
    http://eel.is/c/+draft/dcl.attr.contract#check-3

    View Slide

  142. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 142/171
    Let’s explore!
    https://github.com/arcosuc3m/clang-contracts
    Fork from clang-6
    http://fragata.arcos.inf.uc3m.es/#

    View Slide

  143. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 143/171
    Let’s explore!
    https://github.com/arcosuc3m/clang-contracts
    Fork from clang-6
    http://fragata.arcos.inf.uc3m.es/#
    -build-level=(off|default|audit)

    View Slide

  144. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 144/171
    When contracts are violated in C++20

    View Slide

  145. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 145/171
    When contracts are violated in C++20
    5# The violation handler of a program is a function of type “noexcept
    opt
    function
    of (lvalue reference to const std/:contract_ violation) returning void”. The
    violation handler is invoked when the predicate of a checked contract evaluates
    to false (called a contract violation). There should be no programmatic way of
    setting or modifying the violation handler. It is implementation-defined how the
    violation handler is established for a program and how the
    std /: contract_ violation argument value is set, except as specified below. If a
    precondition is violated, the source location of the violation is implementation-
    defined. [ Note: Implementations are encouraged but not required to report the
    caller site. — end note ] If a postcondition is violated, the source location of the
    violation is the source location of the function definition. If an assertion is
    violated, the source location of the violation is the source location of the
    statement to which the assertion is applied.
    http://eel.is/c/+draft/dcl.attr.contract#check-5

    View Slide

  146. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 146/171
    When contracts are violated in C++20
    5# The violation handler of a program is a function of type “noexcept
    opt
    function
    of (lvalue reference to const std/:contract_ violation) returning void”. The
    violation handler is invoked when the predicate of a checked contract evaluates
    to false (called a contract violation). There should be no programmatic way of
    setting or modifying the violation handler. It is implementation-defined how the
    violation handler is established for a program and how the
    std /: contract_ violation argument value is set, except as specified below. If a
    precondition is violated, the source location of the violation is implementation-
    defined. [ Note: Implementations are encouraged but not required to report the
    caller site. — end note ] If a postcondition is violated, the source location of the
    violation is the source location of the function definition. If an assertion is
    violated, the source location of the violation is the source location of the
    statement to which the assertion is applied.
    http://eel.is/c/+draft/dcl.attr.contract#check-5

    View Slide

  147. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 147/171
    When contracts are violated in C++20
    5# The violation handler of a program is a function of type “noexcept
    opt
    function
    of (lvalue reference to const std/:contract_ violation) returning void”. The
    violation handler is invoked when the predicate of a checked contract evaluates
    to false (called a contract violation). There should be no programmatic way of
    setting or modifying the violation handler. It is implementation-defined how the
    violation handler is established for a program and how the
    std /: contract_ violation argument value is set, except as specified below. If a
    precondition is violated, the source location of the violation is implementation-
    defined. [ Note: Implementations are encouraged but not required to report the
    caller site. — end note ] If a postcondition is violated, the source location of the
    violation is the source location of the function definition. If an assertion is
    violated, the source location of the violation is the source location of the
    statement to which the assertion is applied.
    http://eel.is/c/+draft/dcl.attr.contract#check-5
    16.8.2 Class contract_ violation [support.contract.cviol]
    namespace std {
    class contract_violation {
    public:
    uint_least32_t line_number() const noexcept;
    string_view file_name() const noexcept;
    string_view function_name() const noexcept;
    string_view comment() const noexcept;
    string_view assertion_level() const noexcept;
    };
    }
    http://eel.is/c/+draft/support.contract.cviol

    View Slide

  148. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 148/171
    When contracts are violated in C++20
    5# The violation handler of a program is a function of type “noexcept
    opt
    function
    of (lvalue reference to const std/:contract_ violation) returning void”. The
    violation handler is invoked when the predicate of a checked contract evaluates
    to false (called a contract violation). There should be no programmatic way of
    setting or modifying the violation handler. It is implementation-defined how the
    violation handler is established for a program and how the
    std /: contract_ violation argument value is set, except as specified below. If a
    precondition is violated, the source location of the violation is implementation-
    defined. [ Note: Implementations are encouraged but not required to report the
    caller site. — end note ] If a postcondition is violated, the source location of the
    violation is the source location of the function definition. If an assertion is
    violated, the source location of the violation is the source location of the
    statement to which the assertion is applied.
    http://eel.is/c/+draft/dcl.attr.contract#check-5

    View Slide

  149. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 149/171
    When contracts are violated in C++20
    5# The violation handler of a program is a function of type “noexcept
    opt
    function
    of (lvalue reference to const std/:contract_ violation) returning void”. The
    violation handler is invoked when the predicate of a checked contract evaluates
    to false (called a contract violation). There should be no programmatic way of
    setting or modifying the violation handler. It is implementation-defined how the
    violation handler is established for a program and how the
    std /: contract_ violation argument value is set, except as specified below. If a
    precondition is violated, the source location of the violation is implementation-
    defined. [ Note: Implementations are encouraged but not required to report the
    caller site. — end note ] If a postcondition is violated, the source location of the
    violation is the source location of the function definition. If an assertion is
    violated, the source location of the violation is the source location of the
    statement to which the assertion is applied.
    http://eel.is/c/+draft/dcl.attr.contract#check-5

    View Slide

  150. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 150/171
    When contracts are violated in C++20
    5# The violation handler of a program is a function of type “noexcept
    opt
    function
    of (lvalue reference to const std/:contract_ violation) returning void”. The
    violation handler is invoked when the predicate of a checked contract evaluates
    to false (called a contract violation). There should be no programmatic way of
    setting or modifying the violation handler. It is implementation-defined how the
    violation handler is established for a program and how the
    std /: contract_ violation argument value is set, except as specified below. If a
    precondition is violated, the source location of the violation is implementation-
    defined. [ Note: Implementations are encouraged but not required to report the
    caller site. — end note ] If a postcondition is violated, the source location of the
    violation is the source location of the function definition. If an assertion is
    violated, the source location of the violation is the source location of the
    statement to which the assertion is applied.
    http://eel.is/c/+draft/dcl.attr.contract#check-5

    View Slide

  151. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 151/171
    Let’s explore!
    https://github.com/arcosuc3m/clang-contracts
    Fork from clang-6
    -build-level=(off|default|audit)
    http://fragata.arcos.inf.uc3m.es/#

    View Slide

  152. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 152/171
    Let’s explore!
    https://github.com/arcosuc3m/clang-contracts
    Fork from clang-6
    http://fragata.arcos.inf.uc3m.es/#
    -build-level=(off|default|audit)
    -contract-violation-handler=function

    View Slide

  153. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 153/171
    When contracts are violated in C++20

    View Slide

  154. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 154/171
    When contracts are violated in C++20
    A translation may be performed with one of the following violation
    continuation modes: off or on. A translation with violation continuation
    mode set to off terminates execution by invoking the function
    std/:terminate ([except.terminate]) after completing the execution of
    the violation handler. A translation with a violation continuation mode set
    to on continues execution after completing the execution of the violation
    handler. If no continuation mode is explicitly selected, the default
    continuation mode is off. [ Note: A continuation mode set to on provides
    the opportunity to install a logging handler to instrument a pre-existing
    code base and fix errors before enforcing checks. — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#check-7

    View Slide

  155. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 155/171
    When contracts are violated in C++20
    A translation may be performed with one of the following violation
    continuation modes: off or on. A translation with violation continuation
    mode set to off terminates execution by invoking the function
    std/:terminate ([except.terminate]) after completing the execution of
    the violation handler. A translation with a violation continuation mode set
    to on continues execution after completing the execution of the violation
    handler. If no continuation mode is explicitly selected, the default
    continuation mode is off. [ Note: A continuation mode set to on provides
    the opportunity to install a logging handler to instrument a pre-existing
    code base and fix errors before enforcing checks. — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#check-7

    View Slide

  156. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 156/171
    When contracts are violated in C++20
    A translation may be performed with one of the following violation
    continuation modes: off or on. A translation with violation continuation
    mode set to off terminates execution by invoking the function
    std/:terminate ([except.terminate]) after completing the execution of
    the violation handler. A translation with a violation continuation mode set
    to on continues execution after completing the execution of the violation
    handler. If no continuation mode is explicitly selected, the default
    continuation mode is off. [ Note: A continuation mode set to on provides
    the opportunity to install a logging handler to instrument a pre-existing
    code base and fix errors before enforcing checks. — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#check-7

    View Slide

  157. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 157/171
    When contracts are violated in C++20
    A translation may be performed with one of the following violation
    continuation modes: off or on. A translation with violation continuation
    mode set to off terminates execution by invoking the function
    std/:terminate ([except.terminate]) after completing the execution of
    the violation handler. A translation with a violation continuation mode set
    to on continues execution after completing the execution of the violation
    handler. If no continuation mode is explicitly selected, the default
    continuation mode is off. [ Note: A continuation mode set to on provides
    the opportunity to install a logging handler to instrument a pre-existing
    code base and fix errors before enforcing checks. — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#check-7

    View Slide

  158. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 158/171
    When contracts are violated in C++20
    A translation may be performed with one of the following violation
    continuation modes: off or on. A translation with violation continuation
    mode set to off terminates execution by invoking the function
    std/:terminate ([except.terminate]) after completing the execution of
    the violation handler. A translation with a violation continuation mode set
    to on continues execution after completing the execution of the violation
    handler. If no continuation mode is explicitly selected, the default
    continuation mode is off. [ Note: A continuation mode set to on provides
    the opportunity to install a logging handler to instrument a pre-existing
    code base and fix errors before enforcing checks. — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#check-7
    [ Example:
    void f(int x) [[expects: x > 0]];
    void g() {
    f(0); // std /: terminate() after handler if
    // continuation mode is off;
    // proceeds after handler if
    // continuation mode is on
    /* //. //
    }
    — end example ]

    View Slide

  159. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 159/171
    When contracts are violated in C++20
    A translation may be performed with one of the following violation
    continuation modes: off or on. A translation with violation continuation
    mode set to off terminates execution by invoking the function
    std/:terminate ([except.terminate]) after completing the execution of
    the violation handler. A translation with a violation continuation mode set
    to on continues execution after completing the execution of the violation
    handler. If no continuation mode is explicitly selected, the default
    continuation mode is off. [ Note: A continuation mode set to on provides
    the opportunity to install a logging handler to instrument a pre-existing
    code base and fix errors before enforcing checks. — end note ]
    http://eel.is/c/+draft/dcl.attr.contract#check-7
    P1429r0 - Contracts that work
    Joshua Bern, John Lakos
    Distinguishing between violations that can be safely continued from,
    and violations that are fatal.

    View Slide

  160. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 160/171
    Programming with Contracts in C++20
    Björn Fahller

    View Slide

  161. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 161/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    View Slide

  162. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 162/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    View Slide

  163. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 163/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    View Slide

  164. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 164/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    View Slide

  165. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 165/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    Interesting gotchas:

    Modifying parameter values, and template specializations comes to
    mind.

    View Slide

  166. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 166/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    Interesting gotchas:

    Modifying parameter values, and template specializations comes to
    mind.

    Contracts can be used by static analysis tools and the optimizer.

    View Slide

  167. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 167/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    Interesting gotchas:

    Modifying parameter values, and template specializations comes to
    mind.

    Contracts can be used by static analysis tools and the optimizer.

    Configurable levels of contracts, e.g. full in debug builds, only cheap
    ones in release.

    View Slide

  168. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 168/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    Interesting gotchas:

    Modifying parameter values, and template specializations comes to
    mind.

    Contracts can be used by static analysis tools and the optimizer.

    Configurable levels of contracts, e.g. full in debug builds, only cheap
    ones in release.
    P1426r0 Pull the Plug on Contracts?
    Nathan Meyers.
    Argues that the whole idea got wrong and should
    be scrapped and replaced with something else.

    View Slide

  169. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 169/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    Interesting gotchas:

    Modifying parameter values, and template specializations comes to
    mind.

    Contracts can be used by static analysis tools and the optimizer.

    Configurable levels of contracts, e.g. full in debug builds, only cheap
    ones in release.

    Prefer to express semantics using the type system, if you can.

    View Slide

  170. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 170/171
    Summary

    Design by contract is a way to clarify the responsibility between a
    function implementation and its callers.

    Language support is coming in C++20

    But it’s lacking class invariants

    and post conditions cannot refer to pre-call state.

    Interesting gotchas:

    Modifying parameter values, and template specializations comes to
    mind.

    Contracts can be used by static analysis tools and the optimizer.

    Configurable levels of contracts, e.g. full in debug builds, only cheap
    ones in release.

    Prefer to express semantics using the type system, if you can.
    Play with it!
    https://github.com/arcosuc3m/clang-contracts
    Fork from clang-6
    http://fragata.arcos.inf.uc3m.es/#

    View Slide

  171. Programming with Contracts in C++20 – C++onSea 2019 © Björn Fahller @bjorn_fahller 171/171
    Björn Fahller
    Programming with Contracts in C++20
    [email protected]
    @bjorn_fahller
    @rollbear

    View Slide