mirror of
https://github.com/boostorg/contract.git
synced 2026-01-29 07:22:21 +00:00
310 lines
32 KiB
HTML
Executable File
310 lines
32 KiB
HTML
Executable File
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
|
<title>Quick Start</title>
|
|
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
|
<link href="tabs.css" rel="stylesheet" type="text/css">
|
|
</head><body>
|
|
<!-- Generated by Doxygen 1.5.5 -->
|
|
<div class="navigation" id="top">
|
|
<div class="tabs">
|
|
<ul>
|
|
<li><a href="index.html"><span>Main Page</span></a></li>
|
|
<li><a href="pages.html"><span>Related Pages</span></a></li>
|
|
<li><a href="namespaces.html"><span>Namespaces</span></a></li>
|
|
<li><a href="annotated.html"><span>Classes</span></a></li>
|
|
<li><a href="files.html"><span>Files</span></a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="contents">
|
|
<h1><a class="anchor" name="Quick_Start">Quick Start </a></h1><div align="right"><small> <a class="el" href="index.html#index">Previous</a> | <a class="el" href="Design_By_Contract.html">Next</a> </small></div><p>
|
|
This section briefly shows how to use this library to write contracts.<h2><a class="anchor" name="Conventions">
|
|
Conventions</a></h2>
|
|
This library provides both a <em>macro-based API</em> and a <em>code-based API</em> to write contracts. The code-based API relies less on macros, allows to more easily understand how the library works, but requires the programmer to write much more "setup code" and does not support automatic contract documentation. The use of the macro-based API is recommended whenever possible because it makes the contracts more readable and it is less work for the programmer. This section illustrates the macro-based API while both APIs are explained in later sections.<p>
|
|
This library defines most of its symbols in the <code><a class="el" href="namespacedbc.html" title="Namespace containing the library symbols.">dbc</a></code> namespace. Futhermore, all library macros are prefixed by <code>DBC_</code> (C++ macros are not local to any namespace). Any library symbol (class, function, variable, macro, etc) ending with an underscore <code>_</code> is implementation specific and <em>must not</em> be used directly so it is left out of this documentation. Some library symbols are defined into the global namespace and at the class scope when contracts are added to a user defined classes (this is because the user classes have to be "augmented" with symbols defining their contracts). All these symbols defined by this library outside the <code><a class="el" href="namespacedbc.html" title="Namespace containing the library symbols.">dbc</a></code> namespace have names of the form <code>dbc_</code>..._ where the leading <code>dbc_</code> attempts to avoid name clashes and the ending underscore indicates that these symbols are implementation specific and must not be used. Metapgrogramming constructs used by this library and listed by this documentation are indicated with implementation specific names ending with <code>_</code> (as they should not be used directly).<h2><a class="anchor" name="Platform">
|
|
Platform</a></h2>
|
|
This library is highly portable. It only requires the following:<ol type=1>
|
|
<li>The <a class="el" href="Bibliography.html#Boost">Boost C++ library</a>.</li><li>A C++ standard compiler.</li></ol>
|
|
<p>
|
|
This library has been developed under <a class="el" href="Bibliography.html#Ubuntu">Ubuntu</a> Linux and this documentation makes explicit references to Linux commands. However, if you are using an operating system different from Linux, it should be trivial to mirror the commands used by this documentation into the equivalent ones for your operating system.<p>
|
|
This library has been developed using the Boost C++ library version 1.34.1. Boost is a highly portable C++ library that is available for a variety of platforms. For example, on Ubuntu Linux, assuming your computer is properly connected to the Internet, you can install Boost simply using:<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
$ sudo apt-get install libboost-dev
|
|
</pre></div><p>
|
|
<dl class="note" compact><dt><b>Note:</b></dt><dd>Boost is used by this library implementation for the followings: <ul>
|
|
<li>
|
|
Boost.Preprocessor for preprocessor metaprogramming (essentially to support an arbitrary number of function arguments as specified by <code>DBC_CONFIG_MAX_ARGC</code>). </li>
|
|
<li>
|
|
Boost.MPL for template metaprogramming (essentially for type traits, to support <code><a class="el" href="classdbc_1_1copyable.html" title="Indicate the specified type is copyable to support the "old" postfix in...">dbc::copyable</a></code>, and to generate the <code>DBC_ERROR_</code>... compile-time errors for improper library use). </li>
|
|
</ul>
|
|
Earlier versions of this library did not rely on Boost but the implementation required quite a bit of manual (and error prone) code duplication to deal with multiple function arguments, a good deal of type traits reimplementation, and provided no compile-time checking for improper library use.</dd></dl>
|
|
This library has been developed using the <code>g++</code> C++ compiler version 4.2.4. For example, on Ubuntu Linux you can install <code>g++</code> using:<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
$ sudo apt-get install g++-4.2
|
|
</pre></div><h2><a class="anchor" name="Installation">
|
|
Installation</a></h2>
|
|
You can download the latest release of this library at <a href="http://sourceforge.net/projects/dbcpp/">http://sourceforge.net/projects/dbcpp/</a> . On Linux, you can unpack the compressed downloaded file using:<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
$ tar -xzf dbcpp_<VERSION>.tar.gz
|
|
</pre></div><p>
|
|
This creates a directory <code>"dbcpp_<VERSION>/"</code> that contains the library source files, examples, documentation, etc.<p>
|
|
<dl class="note" compact><dt><b>Note:</b></dt><dd>In the rest of this documentation, we will refer to this directory explicitly as <code>"$DBC_ROOT"</code> or implicitly when a file path is local (e.g., <code>"inlucde/"</code> implicitly indicates <code>"$DBC_ROOT/include/"</code>). Furthermore, command prompts that indicate the directory explicitly as in <code>[$DBC_ROOT]$ <em>command</em></code> require the specified command to be executed from the indicated directory. Otherwise, if the prompt does not indicate any directory as in <code>$ <em>command</em></code> then the command can be executed from the local directory or any directory.</dd></dl>
|
|
This library is composed of header files only (there is no pre-compiled object file). You can install the library simply by copying <em>all</em> contents of the <code>"$DBC_ROOT/include/"</code> directory into a directory that is part of your complier's include path. For example, on Linux you can copy the library header files to the <code>"/usr/include/"</code> directory (you might need to be root):<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
[$DBC_ROOT]$ sudo cp -r include/ /usr/include/
|
|
</pre></div><p>
|
|
Or, you can install the library in some other directory and add that directory to the compiler include path (use the <code>-I</code> option for the <code>g++</code> complier).<p>
|
|
<dl compact><dt><b><a class="el" href="todo.html#_todo000002">Todo:</a></b></dt><dd>Add short table with library download directories, mentioning the examples and referencing the books they are from.</dd></dl>
|
|
<h2><a class="anchor" name="Overview">
|
|
Overview</a></h2>
|
|
Design By Contract is characterized by at least four simple assertion mechanisms (see [<a class="el" href="Bibliography.html#Mey97">Mey97</a>]):<ol type=1>
|
|
<li>It is possible to describe the member function's <b>preconditions</b>. These are logical conditions that the programmer of the function excepts to be true when the function is called (e.g., to check constraints on function parameters). <br>
|
|
<br>
|
|
In preconditions, the variable <code>self</code> is a constant reference to the object and constant reference to function arguments can be accessed via thier names <code>argument_name</code>. <br>
|
|
<br>
|
|
</li><li>It is possible to describe the member function's <b>postconditions</b>. These are logical conditions that the programmer expects to be true when the function has ended normally (e.g., to check the result and any side effect that a function has). <br>
|
|
<br>
|
|
In postconditions, constant references to the object and function arguments current value, <em>after</em> the body execution, can be accessed via <code>self.now</code> and <code>argument_name.now</code> respectively. If the object class or function argument types have been declared copyable (using <code><a class="el" href="post_8hpp.html#b10fbb20732d114633c59fa07be8222a" title="This macro marks the specified type copyable so its value before the body execution...">DBC_COPYABLE()</a></code> or <code><a class="el" href="classdbc_1_1copyable.html" title="Indicate the specified type is copyable to support the "old" postfix in...">dbc::copyable</a></code>) then their values <em>before</em> the body was executed can also be accessed, in this case via <code>self.old</code> and <code>argument_name.old</code>. Furthermore, postconditions of non-void member function can access a constant reference to the function returned value via <code>result</code>. <br>
|
|
<br>
|
|
</li><li>It is possible to describe class <b>invariants</b>. These are logical conditions that the programmer expects to be true after the constructor has been executed successfully, before and after the execution of each member function with a contract, and before the destructor is executed (e.g., invariants can define a valid state for all objects of a class). <br>
|
|
<br>
|
|
In invariants, the variable <code>self</code> is a constant reference to the object. <br>
|
|
<br>
|
|
</li><li>It is possible to formalize the notion of overriding a virtual member function via <b>subcontracting</b>. Subcontracting can be justified by substitution principles and it consists of the following rules that the overriding function must obey: <ol>
|
|
<li>
|
|
Preconditions cannot be stronger. </li>
|
|
<li>
|
|
Postconditions cannot be weaker. </li>
|
|
<li>
|
|
Invariants are inherited and can never be weaker in derived class. </li>
|
|
</ol>
|
|
When subcontracting, this library automatically <em>OR</em> preconditions, <em>AND</em> postconditions and invariants between the contracts of the base and derived classes so to implement these rules. <br>
|
|
<br>
|
|
This library allows to specify that a contract in a derived class subcontracts the related contract in the base class via the <code><a class="el" href="mfun_8hpp.html#1c6dab06912180abfed3dc7f5b3006e3" title="This macro specifies the base class from which an overriding member function is subcontracting...">DBC_BASE()</a></code> macro or the <code>B</code> template argument of <code>dbc::fum::mem</code>.</li></ol>
|
|
<p>
|
|
Based on the above definitions of preconditions, postconditions, and invariants, this library implements the following call semantics for every member function, constructor, and destructor for which the programmer provides a contract (as indicated in [<a class="el" href="Bibliography.html#Mey97">Mey97</a>], [<a class="el" href="Bibliography.html#Ott04">Ott04</a>], and [<a class="el" href="Bibliography.html#Str97">Str97</a>]):<ul>
|
|
<li><a class="anchor" name="Constructor_Call_Semantics"></a> <b>Constructor Call Semantic</b> <br>
|
|
A constructor call executes the following steps:<ol type=a>
|
|
<li>Initialize member variables (via the constructor's member initialization block).</li><li>Check preconditions but not invariants. Constructor preconditions have no access to <code>self</code>. Before constructor body execution, there is no object and invariants do not have to hold.</li><li>Execute constructor body.</li><li>Check invariants.</li><li>Check postconditions.</li></ol>
|
|
</li><li><b>Destructor Call Semantic</b> <br>
|
|
A destructor call executes the following steps:<ol type=a>
|
|
<li>Check invariants (but only if destructor was not called during stack unwinding because of a previously thrown and not yet handled exception). In case of failure, <code><a class="el" href="namespacedbc.html#d6b88f4dab92db77200e6e2c2d41f662" title="The default handler called if destructor contract violation attempts to throw an...">broken_destructor_invariant()</a></code> is be called instead of throwing an exception (this is to comply with C++ STL exception safety requirements, see [<a class="el" href="Bibliography.html#Ott04">Ott04</a>] and [<a class="el" href="Bibliography.html#Str97">Str97</a>]).</li><li>Execute destructor body. After destructor body execution, there is no object anymore so invariants are not checked.</li></ol>
|
|
</li><li><a class="anchor" name="Member_Function_Call_Semantics"></a> <b>Member Function Call Semantics</b> <br>
|
|
A member function executes the following steps:<ol type=a>
|
|
<li>Check invariant <em>and</em> (when subcontracting) check base class function's invariants.</li><li>Check preconditions <em>or</em> (when subcontracting) check base class function's preconditions.</li><li>Execute function body.</li><li>Check invariant <em>and</em> (when subcontracting) check base class function's invariants.</li><li>Check postconditions <em>and</em> (when subcontracting) check base class function's postconditions.</li></ol>
|
|
</li></ul>
|
|
<p>
|
|
In the above rules, <em>"and"</em> and <em>"or"</em> are evaluated in curt-circuit (i.e., A <em>and</em> B evaluates B only if A is evaluated to be true, A <em>or</em> B evaluates B only if A is evaluated to be false).<p>
|
|
Once the programmer has specified contracts, the library provides a mechanism for checking whether the conditions hold at run-time. The <code>DBC_CHECK_</code>... macros can be used to turn this run-time checking on or off selectively for the sake of efficiency (e.g., only compile and check invariants and preconditions but no postconditions). If a condition fails, the library will throw an exception by default but a mechanism is provided for the programmer to specify conditions that throw user defined exceptions, terminate, or exit the program. Furthermore, the programmer can selectively chose which of these conditions should be checked using the <code>DBC_CONFIG_ENABLE_</code>... macros (e.g., only check conditions that terminate or the program but no the ones that throw exceptions).<h2><a class="anchor" name="A_Complete_Example">
|
|
A Complete Example</a></h2>
|
|
This is a fully working example that illustrates how to write contracts using the library macro-based API (from <code>"example/str/str.cpp"</code>).<p>
|
|
<div class="fragment"><pre class="fragment"><span class="comment">/**</span>
|
|
<span class="comment"> * @file</span>
|
|
<span class="comment"> * @author Copyright (C) 2009 Lorenzo Caminiti.</span>
|
|
<span class="comment"> * Distributed under DBC++ Software License (see file LICENSE_1_0.txt).</span>
|
|
<span class="comment"> */</span>
|
|
|
|
<span class="preprocessor">#include <<a class="code" href="dbc_8hpp.html" title="Header file to include the entire Design By Contract for C++ library.">dbc.hpp</a>></span>
|
|
<span class="preprocessor">#include <cstring></span>
|
|
<span class="preprocessor">#include <iostream></span>
|
|
<span class="comment"></span>
|
|
<span class="comment">/** Demonstrate Design By Contract use implementing a simple string type. */</span>
|
|
<span class="keyword">class </span>str <a class="code" href="object_8hpp.html#126883cfec96cafb25d481c5b1e6df61" title="This macro must follow the class type name and it privately derives the class from...">DBC_INHERIT_OBJECT</a>(str) { <span class="comment">// Derive from dbc::object.</span>
|
|
<span class="keyword">public</span>:<span class="comment"></span>
|
|
<span class="comment"> /** Max limit on string length. */</span>
|
|
<span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">size_t</span> MAX_SIZE = 16000;
|
|
<span class="comment"></span>
|
|
<span class="comment"> /**</span>
|
|
<span class="comment"> * Construct from C-style null-terminated string.</span>
|
|
<span class="comment"> * @param[in] chars C-style null-terminated string.</span>
|
|
<span class="comment"> */</span>
|
|
str(<span class="keyword">const</span> <span class="keywordtype">char</span>* chars): size_(), chars_()
|
|
<a class="code" href="mfun_8hpp.html#11cd5419adfe39cba4983b81dca63a71" title="This macro must follow the constructor declaration matching the specified signature...">DBC_CONSTRUCTOR</a>( (public) (str)( (const char*)(chars) ), {
|
|
<span class="comment">// Constructor preconditions.</span>
|
|
<span class="keywordtype">size_t</span> size = strlen(chars); <span class="comment">// Code allowed but keep it simple.</span>
|
|
<span class="comment">// Use DBC_ASSERT() or DBC_ASSERT_STREAM() to assert conditions.</span>
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(size >= 0 && size < str::MAX_SIZE, <span class="stringliteral">"size in range"</span>);
|
|
}, {
|
|
<span class="comment">// Constructor postconditions.</span>
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(<span class="keyword">self</span>.now.size() == strlen(chars.now), <span class="stringliteral">"size set"</span>);
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(strncmp(<span class="keyword">self</span>.now.chars_, chars.now, <span class="keyword">self</span>.now.size_) == 0,
|
|
<span class="stringliteral">"chars set"</span>);
|
|
}, {
|
|
<span class="comment">// Constructor body.</span>
|
|
size_ = strlen(chars);
|
|
chars_ = <span class="keyword">new</span> <span class="keywordtype">char</span>[size_];
|
|
strncpy(chars_, chars, size_);
|
|
})
|
|
<span class="comment"></span>
|
|
<span class="comment"> /**</span>
|
|
<span class="comment"> * Construct copying from another string object.</span>
|
|
<span class="comment"> * Copy constructor is used by library to support "old" in postcond. User</span>
|
|
<span class="comment"> * defined copy constr is needed for pointer deep copy.</span>
|
|
<span class="comment"> * @note To avoid code duplication, this and the above constructor could </span>
|
|
<span class="comment"> * be refactored delegating implementation and contract to an init() func.</span>
|
|
<span class="comment"> * @param[in] other Other string object.</span>
|
|
<span class="comment"> */</span>
|
|
str(<span class="keyword">const</span> str& other): size_(), chars_()
|
|
<a class="code" href="mfun_8hpp.html#11cd5419adfe39cba4983b81dca63a71" title="This macro must follow the constructor declaration matching the specified signature...">DBC_CONSTRUCTOR</a>( (public) (str)( (const str&)(other) ), {
|
|
<span class="comment">// Use other.size() not other.size_ as precond should use public member.</span>
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(other.size() >= 0 && other.size() < str::MAX_SIZE,
|
|
<span class="stringliteral">"size in range"</span>);
|
|
}, {
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(<span class="keyword">self</span>.now.size() == other.now.size_, <span class="stringliteral">"size set"</span>);
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(strncmp(<span class="keyword">self</span>.now.chars_, other.now.chars_, other.now.size_)
|
|
== 0, <span class="stringliteral">"chars set"</span>);
|
|
}, {
|
|
size_ = other.size_;
|
|
chars_ = <span class="keyword">new</span> <span class="keywordtype">char</span>[size_];
|
|
strncpy(chars_, other.chars_, size_);
|
|
})
|
|
<span class="comment"></span>
|
|
<span class="comment"> /** Destroy. */</span>
|
|
<span class="keyword">virtual</span> ~str()
|
|
<a class="code" href="mfun_8hpp.html#a8a977641739ad90988dccb3bac04a13" title="This macro must follow the destructor declaration matching the specified signature...">DBC_DESTRUCTOR</a>( (public) (virtual) (str)(), {
|
|
<span class="comment">// Destructor body.</span>
|
|
<span class="keyword">delete</span>[] chars_; <span class="comment">// Invariant already checked chars_ != 0.</span>
|
|
})
|
|
<span class="comment"></span>
|
|
<span class="comment"> /**</span>
|
|
<span class="comment"> * Return character at specified index.</span>
|
|
<span class="comment"> * @param[in] index Index position.</span>
|
|
<span class="comment"> * @return str's character at specified position.</span>
|
|
<span class="comment"> */</span>
|
|
<span class="keywordtype">char</span>& <span class="keyword">operator</span>[](<span class="keyword">const</span> <span class="keywordtype">size_t</span>& index)
|
|
<a class="code" href="mfun_8hpp.html#2872f212b72c32e6254e34086e9714bf" title="This macro must follow the member function declaration matching the specified signature...">DBC_MEM_FUN</a>( (<span class="keyword">public</span>) (<span class="keywordtype">char</span>&) <a class="code" href="post_8hpp.html#b10fbb20732d114633c59fa07be8222a" title="This macro marks the specified type copyable so its value before the body execution...">DBC_COPYABLE</a>(str)
|
|
(operator_at)( (<span class="keyword">const</span> <span class="keywordtype">size_t</span>&)(index) ), {
|
|
<span class="comment">// Member function preconditions.</span>
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(index >= 0 && index < <span class="keyword">self</span>.size(), <span class="stringliteral">"index in range"</span>);
|
|
}, {
|
|
<span class="comment">// Member function postconditions.</span>
|
|
<span class="comment">// Not a const mem fun, use 'self.old' for object before body and</span>
|
|
<span class="comment">// make class type DBC_COPYABLE().</span>
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(result == <span class="keyword">self</span>.old.chars_[index.now],
|
|
<span class="stringliteral">"returning char at index"</span>);
|
|
}, {
|
|
<span class="comment">// Member function body.</span>
|
|
<span class="keywordflow">return</span> chars_[index];
|
|
})
|
|
<span class="comment"></span>
|
|
<span class="comment"> /**</span>
|
|
<span class="comment"> * Return size (total number of characters).</span>
|
|
<span class="comment"> * @return str's size.</span>
|
|
<span class="comment"> */</span>
|
|
<span class="keywordtype">size_t</span> size() const
|
|
<a class="code" href="mfun_8hpp.html#2872f212b72c32e6254e34086e9714bf" title="This macro must follow the member function declaration matching the specified signature...">DBC_MEM_FUN</a>( (public) (<span class="keywordtype">size_t</span>) (str) (size)() (const), {
|
|
}, {
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(result == <span class="keyword">self</span>.now.size_, <span class="stringliteral">"returning size"</span>);
|
|
}, {
|
|
<span class="keywordflow">return</span> size_;
|
|
})
|
|
|
|
<span class="keyword">private</span>:<span class="comment"></span>
|
|
<span class="comment"> /** Internal string size. */</span>
|
|
<span class="keywordtype">size_t</span> size_; <span class="comment">// Unsgined so size_ >= 0 check could be removed...</span><span class="comment"></span>
|
|
<span class="comment"> /** Internal string representation. */</span>
|
|
<span class="keywordtype">char</span>* chars_;
|
|
|
|
<a class="code" href="invariant_8hpp.html#fd939e7c1754a61a57c20bb7c6422ed4" title="This macro must be used within the class declaration and it specifies the invariants...">DBC_INVARIANT</a>(str, {
|
|
<span class="comment">// Invariants.</span>
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(<span class="keyword">self</span>.chars_ != 0, <span class="stringliteral">"chars exist"</span>);
|
|
<a class="code" href="assertion_8hpp.html#393d8bc235939371624484cdda853395" title="Assert the specified condition, intended to be used to assert preconditions, postconditions...">DBC_ASSERT</a>(<span class="keyword">self</span>.size_ >= 0 && <span class="keyword">self</span>.size_ < str::MAX_SIZE,
|
|
<span class="stringliteral">"size in range"</span>);
|
|
})
|
|
};
|
|
<span class="comment"></span>
|
|
<span class="comment">/** Main program. */</span>
|
|
<span class="keywordtype">int</span> main() {
|
|
std::cout << std::endl << <span class="stringliteral">"init()..."</span> << std::endl;
|
|
str s(<span class="stringliteral">"Galileo Galilei"</span>);
|
|
|
|
std::cout << std::endl << <span class="stringliteral">"operator[](0)..."</span> << std::endl;
|
|
std::cout << s[0] << std::endl;
|
|
|
|
std::cout << std::endl << <span class="stringliteral">"del()..."</span> << std::endl;
|
|
<span class="keywordflow">return</span> 0;
|
|
}
|
|
|
|
</pre></div><p>
|
|
On Linux, it can be compiled using:<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
[$DBC_ROOT]$ g++ -Wall -I./include -DDBC_ALL -DDBC_CONFIG_LOG_LEVEL=DBC_LOG_LEVEL_ALL ./example/str/str.cpp -o ./build/example/str
|
|
</pre></div><p>
|
|
The <code>DBC_ALL</code> macro is defined (<code>-D</code> option) to indicate that all contracts (preconditions, postconditions, and invariants) should be compiled and checked. The <code>DBC_CONFIG_LOG_LEVEL</code> macro is defined to <code>DBC_LOG_LEVEL_ALL</code> so the library will output debug information on what conditions are being checked (this verbose output is enabled here for demonstration only, usually the <code>DBC_CONFIG_LOG_LEVEL</code> can be left undefined so the DBC library will only log informations in case of a condition failure).<p>
|
|
On Linux, the compiled example program can be executed using:<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
[$DBC_ROOT]$ ./build/example/str
|
|
</pre></div><p>
|
|
Which produces the following output:<p>
|
|
<div class="fragment"><pre class="fragment">
|
|
init()...
|
|
dbc: 3str::init(): entering
|
|
dbc: 3str::init(): checking preconditions
|
|
dbc: Assertion "size in range" passed as { size >= 0 && size < str::MAX_SIZE; } at ./example/str/str.cpp:37
|
|
dbc: 3str::init(): executing body
|
|
dbc: 3str::init(): checking invariant
|
|
dbc: Assertion "chars exist" passed as { self.chars_ != 0; } at ./example/str/str.cpp:113
|
|
dbc: Assertion "size in range" passed as { self.size_ >= 0 && self.size_ < str::MAX_SIZE; } at ./example/str/str.cpp:113
|
|
dbc: 3str::init(): checking postconditions
|
|
dbc: 3str::size(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: Assertion "size set" passed as { self.now.size() == strlen(chars.now); } at ./example/str/str.cpp:37
|
|
dbc: Assertion "chars set" passed as { strncmp(self.now.chars_, chars.now, self.now.size_) == 0; } at ./example/str/str.cpp:37
|
|
dbc: 3str::init(): returning
|
|
|
|
operator[](0)...
|
|
dbc: 3str::operator_at(): entering
|
|
dbc: 3str::init(): entering
|
|
dbc: 3str::init(): checking preconditions
|
|
dbc: 3str::size(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: 3str::size(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: Assertion "size in range" passed as { other.size() >= 0 && other.size() < str::MAX_SIZE; } at ./example/str/str.cpp:60
|
|
dbc: 3str::init(): executing body
|
|
dbc: 3str::init(): checking invariant
|
|
dbc: Assertion "chars exist" passed as { self.chars_ != 0; } at ./example/str/str.cpp:113
|
|
dbc: Assertion "size in range" passed as { self.size_ >= 0 && self.size_ < str::MAX_SIZE; } at ./example/str/str.cpp:113
|
|
dbc: 3str::init(): checking postconditions
|
|
dbc: 3str::size(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: Assertion "size set" passed as { self.now.size() == other.now.size_; } at ./example/str/str.cpp:60
|
|
dbc: Assertion "chars set" passed as { strncmp(self.now.chars_, other.now.chars_, other.now.size_) == 0; } at ./example/str/str.cpp:60
|
|
dbc: 3str::init(): returning
|
|
dbc: post<3str>: copied from original object
|
|
dbc: 3str::operator_at(): checking invariant
|
|
dbc: Assertion "chars exist" passed as { self.chars_ != 0; } at ./example/str/str.cpp:113
|
|
dbc: Assertion "size in range" passed as { self.size_ >= 0 && self.size_ < str::MAX_SIZE; } at ./example/str/str.cpp:113
|
|
dbc: 3str::operator_at(): checking preconditions
|
|
dbc: 3str::size(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: Assertion "index in range" passed as { index >= 0 && index < self.size(); } at ./example/str/str.cpp:88
|
|
dbc: 3str::operator_at(): executing body
|
|
dbc: 3str::operator_at(): checking invariant
|
|
dbc: Assertion "chars exist" passed as { self.chars_ != 0; } at ./example/str/str.cpp:113
|
|
dbc: Assertion "size in range" passed as { self.size_ >= 0 && self.size_ < str::MAX_SIZE; } at ./example/str/str.cpp:113
|
|
dbc: 3str::operator_at(): checking postconditions
|
|
dbc: Assertion "returning char at index" passed as { result == self.old.chars_[index.now]; } at ./example/str/str.cpp:88
|
|
dbc: 3str::init(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: 3str::del(): entering, executing body, and returning (assertions disabled within assertion checking)
|
|
dbc: 3str::operator_at(): returning
|
|
dbc: 3str::del(): entering
|
|
dbc: 3str::del(): checking invariant
|
|
dbc: Assertion "chars exist" passed as { self.chars_ != 0; } at ./example/str/str.cpp:113
|
|
dbc: Assertion "size in range" passed as { self.size_ >= 0 && self.size_ < str::MAX_SIZE; } at ./example/str/str.cpp:113
|
|
dbc: 3str::del(): executing body
|
|
dbc: 3str::del(): returning
|
|
G
|
|
|
|
del()...
|
|
dbc: 3str::del(): entering
|
|
dbc: 3str::del(): checking invariant
|
|
dbc: Assertion "chars exist" passed as { self.chars_ != 0; } at ./example/str/str.cpp:113
|
|
dbc: Assertion "size in range" passed as { self.size_ >= 0 && self.size_ < str::MAX_SIZE; } at ./example/str/str.cpp:113
|
|
dbc: 3str::del(): executing body
|
|
dbc: 3str::del(): returning
|
|
</pre></div><p>
|
|
Note that the library debug output messages (prefixed by <code>"dbc:"</code> and that can be turned off by leaving <code>DBC_CONFIG_LOG_LEVEL</code> undefined) show how preconditions, postconditions, and invariants are checked when constructors, destructor, and member functions are called accordingly to their <a class="el" href="Quick_Start.html#Constructor_Call_Semantics">DBC call semantics</a>.<p>
|
|
Finally, <a href="str/classstr.html">this</a> shows the source code documentation generated by <a class="el" href="Bibliography.html#doxygen">doxygen</a> for this example. Note that preconditions, postconditions, and invariants have been automatically documented by this library.<p>
|
|
<div align="right"><small> <a class="el" href="index.html#index">Previous</a> | <a class="el" href="Design_By_Contract.html">Next</a> </small></div> </div>
|
|
<hr size="1"><address style="text-align: right;"><small>Generated on Wed Jun 17 15:39:36 2009 by
|
|
<a href="http://www.doxygen.org/index.html">
|
|
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.5 </small></address>
|
|
</body>
|
|
</html>
|