2467 lines
282 KiB
HTML
2467 lines
282 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
|
<title>Extras</title>
|
|
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
|
<link rel="home" href="../index.html" title="Chapter 1. Boost.Contract 1.0.0">
|
|
<link rel="up" href="../index.html" title="Chapter 1. Boost.Contract 1.0.0">
|
|
<link rel="prev" href="advanced.html" title="Advanced">
|
|
<link rel="next" href="examples.html" title="Examples">
|
|
</head>
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<table cellpadding="2" width="100%"><tr>
|
|
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
|
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
|
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
|
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
|
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
|
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="advanced.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="examples.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
|
<a name="boost_contract.extras"></a><a class="link" href="extras.html" title="Extras">Extras</a>
|
|
</h2></div></div></div>
|
|
<div class="toc"><dl class="toc">
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.old_value_requirements__templates_">Old
|
|
Value Requirements (Templates)</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.assertion_requirements__templates_">Assertion
|
|
Requirements (Templates)</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.volatile_public_functions">Volatile
|
|
Public Functions</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.move_operations">Move Operations</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.unions">Unions</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.assertion_levels">Assertion Levels</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.disable_contract_checking">Disable
|
|
Contract Checking</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.disable_contract_compilation__macro_interface_">Disable
|
|
Contract Compilation (Macro Interface)</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.separate_body_implementation">Separate
|
|
Body Implementation</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.no_lambda_functions__no_c__11_">No
|
|
Lambda Functions (No C++11)</a></span></dt>
|
|
<dt><span class="section"><a href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_">No
|
|
Macros (and No Variadic Macros)</a></span></dt>
|
|
</dl></div>
|
|
<p>
|
|
This section can be consulted selectively for specific topics of interest.
|
|
</p>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.old_value_requirements__templates_"></a><a class="link" href="extras.html#boost_contract.extras.old_value_requirements__templates_" title="Old Value Requirements (Templates)">Old
|
|
Value Requirements (Templates)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
Old values require to copy the expression passed to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
thus the type of that expression needs to be copyable. More precisely, dereferencing
|
|
an old value pointer of type <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code><code class="computeroutput"><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
|
requires <code class="computeroutput"><a class="link" href="../boost/contract/is_old_value_copyable.html" title="Struct template is_old_value_copyable">boost::contract::is_old_value_copyable</a></code><code class="computeroutput"><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value</span></code> to be <code class="computeroutput"><span class="keyword">true</span></code>,
|
|
otherwise this library will generate a compile-time error.
|
|
</p>
|
|
<p>
|
|
In some cases it might be acceptable, or even desirable, to cause a compile-time
|
|
error when a program uses old value types that are not copyable (because
|
|
it is not possible to fully check the correctness of the program as stated
|
|
by the contract assertions that use these old values). In these cases, programmers
|
|
can declare old values using <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
|
as seen so far.
|
|
</p>
|
|
<p>
|
|
However, in some other cases it might be desirable to simply skip assertions
|
|
that use old values when the respective old value types are not copyable,
|
|
without causing compile-time errors. Programmers can do this using <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>
|
|
instead of <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
|
and checking if the old value pointer is not null before dereferencing it
|
|
in postconditions. For example, consider the following function template
|
|
that could in general be instantiated for types <code class="computeroutput"><span class="identifier">T</span></code>
|
|
that are not copy constructible (that is for which <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">is_old_value_copyable</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value</span></code> is <code class="computeroutput"><span class="keyword">false</span></code>,
|
|
see <a href="../../../example/features/old_if_copyable.cpp" target="_top"><code class="literal">old_if_copyable.cpp</code></a>):
|
|
<a href="#ftn.boost_contract.extras.old_value_requirements__templates_.f0" class="footnote" name="boost_contract.extras.old_value_requirements__templates_.f0"><sup class="footnote">[68]</sup></a>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> <span class="comment">// T might or might not be copyable.</span>
|
|
<span class="keyword">void</span> <span class="identifier">offset</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">count</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// No compiler error if T has no copy constructor...</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr_if_copyable</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">old_x</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">function</span><span class="special">()</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="comment">// ...but old value null if T has no copy constructor.</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">old_x</span><span class="special">)</span> <span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span> <span class="special">+</span> <span class="identifier">count</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">x</span> <span class="special">+=</span> <span class="identifier">count</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The old value pointer <code class="computeroutput"><span class="identifier">old_x</span></code>
|
|
is programmed using <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>.
|
|
When <code class="computeroutput"><span class="identifier">T</span></code> is copyable, this
|
|
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr_if_copyable</span><span class="special">]<</span><span class="identifier">T</span><span class="special">></span></code> behaves
|
|
like <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>.
|
|
When <code class="computeroutput"><span class="identifier">T</span></code> is not copyable instead,
|
|
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr_if_copyable</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> will
|
|
simply not copy <code class="computeroutput"><span class="identifier">x</span></code> at run-time
|
|
and leave <code class="computeroutput"><span class="identifier">old_x</span></code> initialized
|
|
as a null pointer. Therefore, <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>
|
|
objects like <code class="computeroutput"><span class="identifier">old_x</span></code> must be
|
|
checked to be not null as in <code class="computeroutput"><span class="keyword">if</span><span class="special">(</span><span class="identifier">old_x</span><span class="special">)</span> <span class="special">...</span></code> before
|
|
they are dereferenced in postconditions and exception guarantees.
|
|
</p>
|
|
<p>
|
|
If the above example used <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
|
instead then this library would have generated a compile-time error when
|
|
<code class="computeroutput"><span class="identifier">offset</span></code> is instantiated with
|
|
types <code class="computeroutput"><span class="identifier">T</span></code> that are not copy
|
|
constructible (but only if <code class="computeroutput"><span class="identifier">old_x</span></code>
|
|
is actually dereferenced somewhere in the contract assertions using <code class="computeroutput"><span class="special">*</span><span class="identifier">old_x</span> <span class="special">...</span></code>, <code class="computeroutput"><span class="identifier">old_x</span><span class="special">->...</span></code>, etc.).
|
|
</p>
|
|
<p>
|
|
When C++11 <code class="computeroutput"><span class="keyword">auto</span></code> declarations
|
|
are used with <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>,
|
|
this library always defaults to using the <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
|
type (because its type requirements are more stringent than <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>).
|
|
If programmers want to relax the copyable type requirement, they must do
|
|
so explicitly by using <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>
|
|
instead of using <code class="computeroutput"><span class="keyword">auto</span></code>. For example,
|
|
the following statements are equivalent:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">old_x</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// C++11 auto declarations always use `old_ptr` (never `old_ptr_if_copyable`).</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">x</span><span class="special">)></span> <span class="identifier">old_x</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
This library uses <code class="computeroutput"><a class="link" href="../boost/contract/is_old_value_copyable.html" title="Struct template is_old_value_copyable">boost::contract::is_old_value_copyable</a></code>
|
|
to determine if an old value type is copyable or not, and then <code class="computeroutput"><a class="link" href="../boost/contract/old_value_copy.html" title="Struct template old_value_copy">boost::contract::old_value_copy</a></code>
|
|
to actually copy the old value. By default, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">is_old_value_copyable</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
|
is equivalent to <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_copy_constructible</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> and
|
|
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_value_copy</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> is
|
|
implemented using <code class="computeroutput"><span class="identifier">T</span></code>'s copy
|
|
constructor. However, these type traits can be specialized by programmers
|
|
for example to avoid making old value copies of types even when they have
|
|
a copy constructor (maybe because these copy constructors are too expensive),
|
|
or to make old value copies for types that do not have a copy constructor,
|
|
or for any other specific need programmers might have for the types in question.
|
|
For example, the following specialization of <code class="computeroutput"><a class="link" href="../boost/contract/is_old_value_copyable.html" title="Struct template is_old_value_copyable">boost::contract::is_old_value_copyable</a></code>
|
|
intentionally avoids making old value copies for all expressions of type
|
|
<code class="computeroutput"><span class="identifier">w</span></code> even if that type has a
|
|
copy constructor (see <a href="../../../example/features/old_if_copyable.cpp" target="_top"><code class="literal">old_if_copyable.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Copyable type but...</span>
|
|
<span class="keyword">class</span> <span class="identifier">w</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="identifier">w</span><span class="special">(</span><span class="identifier">w</span> <span class="keyword">const</span><span class="special">&)</span> <span class="special">{</span> <span class="comment">/* Some very expensive copy here operation here... */</span> <span class="special">}</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// ...never copy old values for type `w` (because its copy is too expensive).</span>
|
|
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">contract</span> <span class="special">{</span>
|
|
<span class="keyword">template</span><span class="special"><></span>
|
|
<span class="keyword">struct</span> <span class="identifier">is_old_value_copyable</span><span class="special"><</span><span class="identifier">w</span><span class="special">></span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">false_type</span> <span class="special">{};</span>
|
|
<span class="special">}</span> <span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
On the flip side, the following specializations of <code class="computeroutput"><a class="link" href="../boost/contract/is_old_value_copyable.html" title="Struct template is_old_value_copyable">boost::contract::is_old_value_copyable</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/old_value_copy.html" title="Struct template old_value_copy">boost::contract::old_value_copy</a></code>
|
|
make old value copies of expressions of type <code class="computeroutput"><span class="identifier">p</span></code>
|
|
even if that type does not actually have a copy constructor (see <a href="../../../example/features/old_if_copyable.cpp" target="_top"><code class="literal">old_if_copyable.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Non-copyable type but...</span>
|
|
<span class="keyword">class</span> <span class="identifier">p</span> <span class="special">:</span> <span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span> <span class="special">{</span>
|
|
<span class="keyword">int</span><span class="special">*</span> <span class="identifier">num_</span><span class="special">;</span>
|
|
|
|
<span class="keyword">friend</span> <span class="keyword">struct</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_value_copy</span><span class="special"><</span><span class="identifier">p</span><span class="special">>;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// ...still copy old values for type `p` (using a deep copy).</span>
|
|
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">contract</span> <span class="special">{</span>
|
|
<span class="keyword">template</span><span class="special"><></span>
|
|
<span class="keyword">struct</span> <span class="identifier">old_value_copy</span><span class="special"><</span><span class="identifier">p</span><span class="special">></span> <span class="special">{</span>
|
|
<span class="keyword">explicit</span> <span class="identifier">old_value_copy</span><span class="special">(</span><span class="identifier">p</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">old</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="special">*</span><span class="identifier">old_</span><span class="special">.</span><span class="identifier">num_</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">old</span><span class="special">.</span><span class="identifier">num_</span><span class="special">;</span> <span class="comment">// Deep copy pointed value.</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="identifier">p</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">old</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">old_</span><span class="special">;</span> <span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">p</span> <span class="identifier">old_</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">template</span><span class="special"><></span>
|
|
<span class="keyword">struct</span> <span class="identifier">is_old_value_copyable</span><span class="special"><</span><span class="identifier">p</span><span class="special">></span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
|
|
<span class="special">}</span> <span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.extras.old_value_requirements__templates_.h0"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.old_value_requirements__templates_.no_c__11"></a></span><a class="link" href="extras.html#boost_contract.extras.old_value_requirements__templates_.no_c__11">No
|
|
C++11</a>
|
|
</h5>
|
|
<p>
|
|
In general, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_copy_constructible</span></code> and therefore <code class="computeroutput"><a class="link" href="../boost/contract/is_old_value_copyable.html" title="Struct template is_old_value_copyable">boost::contract::is_old_value_copyable</a></code>
|
|
require C++11 <code class="computeroutput"><span class="keyword">decltype</span></code> and SFINAE
|
|
to automatically detect if a given type is not copyable. On non-C++11 compilers,
|
|
it is possible to inherit the old value type from <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span></code>,
|
|
or use <code class="computeroutput"><span class="identifier">BOOST_MOVABLE_BUT_NOT_COPYABLE</span></code>,
|
|
or specialize <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_copy_constructible</span></code> (see <a href="http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/boost_typetraits/reference/is_copy_constructible.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">is_copy_constructible</span></code></a> documentation
|
|
for more information). Alternatively, it is possible to just specialize
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/is_old_value_copyable.html" title="Struct template is_old_value_copyable">boost::contract::is_old_value_copyable</a></code>.
|
|
For example, for a non-copyable type <code class="computeroutput"><span class="identifier">n</span></code>
|
|
(see <a href="../../../example/features/old_if_copyable.cpp" target="_top"><code class="literal">old_if_copyable.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">n</span> <span class="special">{</span> <span class="comment">// Do not want to use boost::noncopyable but...</span>
|
|
<span class="keyword">int</span> <span class="identifier">num_</span><span class="special">;</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">n</span><span class="special">(</span><span class="identifier">n</span> <span class="keyword">const</span><span class="special">&);</span> <span class="comment">// ...unimplemented private copy constructor (so non-copyable).</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Specialize `boost::is_copy_constructible` (no need for this on C++11).</span>
|
|
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">contract</span> <span class="special">{</span>
|
|
<span class="keyword">template</span><span class="special"><></span>
|
|
<span class="keyword">struct</span> <span class="identifier">is_old_value_copyable</span><span class="special"><</span><span class="identifier">n</span><span class="special">></span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">false_type</span> <span class="special">{};</span>
|
|
<span class="special">}</span> <span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.assertion_requirements__templates_"></a><a class="link" href="extras.html#boost_contract.extras.assertion_requirements__templates_" title="Assertion Requirements (Templates)">Assertion
|
|
Requirements (Templates)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
In general, assertions can introduce a new set of requirements on the types
|
|
used by the program. Some of these type requirements might be necessary only
|
|
to check the assertions and they would not be required by the program otherwise.
|
|
</p>
|
|
<p>
|
|
In some cases it might be acceptable, or even desirable, to cause a compile-time
|
|
error when a program uses types that do not provide all the operations needed
|
|
to check contract assertions (because it is not possible to fully check the
|
|
correctness of the program as specified by its contracts). In these cases,
|
|
programmers can specify contract assertions as we have seen so far, compilation
|
|
will fail if user types do not provide all operations necessary to check
|
|
the contracts.
|
|
</p>
|
|
<p>
|
|
However, in some other cases it might be desirable to not augment the type
|
|
requirements of a program because of contract assertions and to simply skip
|
|
these assertions when user types do not provide all the operations necessary
|
|
to check them, without causing compile-time errors. Programmers can do this
|
|
using <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
(or <code class="computeroutput"><a class="link" href="../boost/contract/condition_if_c.html" title="Function template condition_if_c">boost::contract::condition_if_c</a></code>).
|
|
</p>
|
|
<p>
|
|
For example, let's consider the following <code class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
|
class template equivalent to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>.
|
|
C++ <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> does
|
|
not require that its value type parameter <code class="computeroutput"><span class="identifier">T</span></code>
|
|
has an equality operator <code class="computeroutput"><span class="special">==</span></code>
|
|
(it only requires <code class="computeroutput"><span class="identifier">T</span></code> to be
|
|
copy constructible, see <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span></code>
|
|
documentation). However, the contracts for the <code class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">value</span><span class="special">)</span></code>
|
|
public function include a postcondition <code class="computeroutput"><span class="identifier">back</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">value</span></code>
|
|
that introduces the new requirement that <code class="computeroutput"><span class="identifier">T</span></code>
|
|
must also have an equality operator <code class="computeroutput"><span class="special">==</span></code>.
|
|
Programmers can specify this postcondition as usual with <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">back</span><span class="special">()</span>
|
|
<span class="special">==</span> <span class="identifier">value</span><span class="special">)</span></code> an let the program fail to compile when
|
|
users instantiate <code class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
|
with a type <code class="computeroutput"><span class="identifier">T</span></code> that does not
|
|
provide an equality operator <code class="computeroutput"><span class="special">==</span></code>.
|
|
Otherwise, programmers can specify this postcondition using <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
to evaluate the asserted condition only for types <code class="computeroutput"><span class="identifier">T</span></code>
|
|
that have an equality operator <code class="computeroutput"><span class="special">==</span></code>
|
|
(and trivially evaluate to <code class="computeroutput"><span class="keyword">true</span></code>
|
|
otherwise). On C++17 compilers, the same can be achieved using <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
instead of <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
resulting in a more concise and readable syntax. <a href="#ftn.boost_contract.extras.assertion_requirements__templates_.f0" class="footnote" name="boost_contract.extras.assertion_requirements__templates_.f0"><sup class="footnote">[69]</sup></a> For example (see <a href="../../../example/features/condition_if.cpp" target="_top"><code class="literal">condition_if.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Until C++17 (without <code class="computeroutput"><span class="keyword">if</span>
|
|
<span class="keyword">constexpr</span></code>)
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Since C++17 (with <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>)
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">vector</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="comment">// Instead of `ASSERT(back() == value)` for T without `==`.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">condition_if</span><span class="special"><</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">>(</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">equal_to</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(),</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">back</span><span class="special">()),</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">value</span><span class="special">)</span>
|
|
<span class="special">)</span>
|
|
<span class="special">)</span>
|
|
<span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">vect_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">vector</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boot</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="comment">// Guard with `if constexpr` for T without `==`.</span>
|
|
<span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value</span><span class="special">)</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">back</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">value</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">vect_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
More in general, <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
is used as follow:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">condition_if</span><span class="special"><</span><span class="identifier">Pred</span><span class="special">>(</span>
|
|
<span class="identifier">cond</span>
|
|
<span class="special">)</span>
|
|
</pre>
|
|
<p>
|
|
Where <code class="computeroutput"><span class="identifier">Pred</span></code> is a nullary boolean
|
|
meta-function and <code class="computeroutput"><span class="identifier">cond</span></code> is
|
|
a nullary boolean functor. If <code class="computeroutput"><span class="identifier">Pred</span><span class="special">::</span><span class="identifier">value</span></code>
|
|
is statically evaluated to be <code class="computeroutput"><span class="keyword">true</span></code>
|
|
at compile-time then <code class="computeroutput"><span class="identifier">cond</span><span class="special">()</span></code> is called at run-time and its boolean result
|
|
is returned by the enclosing <code class="computeroutput">boost::contract::condition_if</code>
|
|
call. Otherwise, if <code class="computeroutput"><span class="identifier">Pred</span><span class="special">::</span><span class="identifier">value</span></code>
|
|
is statically evaluated to be <code class="computeroutput"><span class="keyword">false</span></code>
|
|
at compile-time then <code class="computeroutput">boost::condition_if</code>
|
|
trivially returns <code class="computeroutput"><span class="keyword">true</span></code>. Therefore,
|
|
if <code class="computeroutput"><span class="identifier">cond</span></code> is a functor template
|
|
instantiation (not just a functor) then its call that contains the assertion
|
|
operations with the extra type requirements (e.g., the equality operator
|
|
<code class="computeroutput"><span class="special">==</span></code>) will not be actually instantiated
|
|
and compiled unless the compiler determines at compile-time that <code class="computeroutput"><span class="identifier">Pred</span><span class="special">::</span><span class="identifier">value</span></code> is <code class="computeroutput"><span class="keyword">true</span></code>
|
|
(functor templates like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">equal_to</span></code>
|
|
and C++14 generic lambdas can be used to program <code class="computeroutput"><span class="identifier">cond</span></code>,
|
|
but C++11 lambdas cannot).
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
function template is a special case of the more general <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>,
|
|
specifically <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">condition_if</span><span class="special"><</span><span class="identifier">Pred</span><span class="special">>(</span><span class="identifier">cond</span><span class="special">)</span></code> is
|
|
equivalent to <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">call_if</span><span class="special"><</span><span class="identifier">Pred</span><span class="special">>(</span><span class="identifier">cond</span><span class="special">).</span><span class="identifier">else_</span><span class="special">([]</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span> <span class="special">})</span></code>.
|
|
<a href="#ftn.boost_contract.extras.assertion_requirements__templates_.f1" class="footnote" name="boost_contract.extras.assertion_requirements__templates_.f1"><sup class="footnote">[70]</sup></a> The <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>
|
|
function template accepts a number of optional <span class="emphasis"><em>else-if</em></span>
|
|
statements and one optional <span class="emphasis"><em>else</em></span> statement:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">call_if</span><span class="special"><</span><span class="identifier">Pred1</span><span class="special">>(</span>
|
|
<span class="identifier">t1</span>
|
|
<span class="special">).</span><span class="keyword">template</span> <span class="identifier">else_if</span><span class="special"><</span><span class="identifier">Pred2</span><span class="special">>(</span> <span class="comment">// Optional.</span>
|
|
<span class="identifier">t2</span>
|
|
<span class="special">)</span>
|
|
<span class="special">...</span> <span class="comment">// Optionally, other `else_if` statements.</span>
|
|
<span class="special">.</span><span class="identifier">else_</span><span class="special">(</span> <span class="comment">// Optional for `void` functors, otherwise required.</span>
|
|
<span class="identifier">e</span>
|
|
<span class="special">)</span>
|
|
</pre>
|
|
<p>
|
|
Where <code class="computeroutput"><span class="identifier">Pred1</span></code>, <code class="computeroutput"><span class="identifier">Pred2</span></code>, ... are nullary boolean meta-functions
|
|
and <code class="computeroutput"><span class="identifier">t1</span></code>, <code class="computeroutput"><span class="identifier">t2</span></code>,
|
|
..., <code class="computeroutput"><span class="identifier">e</span></code> are nullary functors.
|
|
The return types of the functor calls <code class="computeroutput"><span class="identifier">t1</span><span class="special">()</span></code>, <code class="computeroutput"><span class="identifier">t2</span><span class="special">()</span></code>, ..., <code class="computeroutput"><span class="identifier">e</span><span class="special">()</span></code> must either be all the same (possibly all
|
|
<code class="computeroutput"><span class="keyword">void</span></code>) or be of types implicitly
|
|
convertible into one another. At run-time <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>
|
|
will call the functor <code class="computeroutput"><span class="identifier">t1</span><span class="special">()</span></code>, or <code class="computeroutput"><span class="identifier">t2</span><span class="special">()</span></code>, ..., or <code class="computeroutput"><span class="identifier">e</span><span class="special">()</span></code> depending on which meta-function <code class="computeroutput"><span class="identifier">Pred1</span><span class="special">::</span><span class="identifier">value</span></code>, <code class="computeroutput"><span class="identifier">Pred2</span><span class="special">::</span><span class="identifier">value</span></code>,
|
|
... is statically evaluated to be <code class="computeroutput"><span class="keyword">true</span></code>
|
|
or <code class="computeroutput"><span class="keyword">false</span></code> at compile-time, and
|
|
it will return the value returned by the functor being called. If <code class="computeroutput"><span class="identifier">t1</span></code>, <code class="computeroutput"><span class="identifier">t2</span></code>,
|
|
..., <code class="computeroutput"><span class="identifier">e</span></code> are nullary functor
|
|
template instantiations (not just nullary functors) then their code will
|
|
only be compiled if the compiler determines they need to be actually called
|
|
at run-time (so only if the related <code class="computeroutput"><span class="identifier">Pred1</span><span class="special">::</span><span class="identifier">value</span></code>,
|
|
<code class="computeroutput"><span class="identifier">Pred2</span><span class="special">::</span><span class="identifier">value</span></code>, ... are respectively evaluated to
|
|
be <code class="computeroutput"><span class="keyword">true</span></code> or <code class="computeroutput"><span class="keyword">false</span></code>
|
|
at compile-time). All the <code class="computeroutput"><span class="identifier">else_if</span><span class="special"><...>(...)</span></code> statements are optional.
|
|
The <code class="computeroutput"><span class="identifier">else_</span><span class="special">(...)</span></code>
|
|
statement is optional if the functor calls return <code class="computeroutput"><span class="keyword">void</span></code>,
|
|
otherwise it is required.
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput"><a class="link" href="../boost/contract/condition_if_c.html" title="Function template condition_if_c">boost::contract::condition_if_c</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/call_if_c.html" title="Function template call_if_c">boost::contract::call_if_c</a></code>,
|
|
and <code class="computeroutput"><span class="special">.</span><span class="identifier">else_if_c</span></code>
|
|
function templates work similarly to their counterparts without the <code class="computeroutput"><span class="special">...</span><span class="identifier">_c</span></code> postfix
|
|
seen so far, but they take their predicate template parameters as static
|
|
boolean values instead of nullary boolean meta-functions.
|
|
</p>
|
|
<p>
|
|
In general, <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>
|
|
can be used to program contract assertions that compile and check different
|
|
functor templates depending on related predicates being statically evaluated
|
|
to be <code class="computeroutput"><span class="keyword">true</span></code> or <code class="computeroutput"><span class="keyword">false</span></code> at compile-time (but in most cases
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
should be sufficient and less verbose to use). On compilers that support
|
|
C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
there should be no need to use <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
or <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>
|
|
because <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
can be used instead (making the code more readable and easier to program).
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.extras.assertion_requirements__templates_.h0"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.assertion_requirements__templates_.if_constexpr_emulation__c__14_"></a></span><a class="link" href="extras.html#boost_contract.extras.assertion_requirements__templates_.if_constexpr_emulation__c__14_">If-Constexpr
|
|
Emulation (C++14)</a>
|
|
</h5>
|
|
<p>
|
|
A part from its use within contracts, on C++14 compilers <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>
|
|
can be used together with C++14 generic lambdas to emulate C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>.
|
|
<a href="#ftn.boost_contract.extras.assertion_requirements__templates_.f2" class="footnote" name="boost_contract.extras.assertion_requirements__templates_.f2"><sup class="footnote">[71]</sup></a> For example (see <a href="../../../example/features/call_if_cxx14.cpp" target="_top"><code class="literal">call_if_cxx14.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Until C++17 (without <code class="computeroutput"><span class="keyword">if</span>
|
|
<span class="keyword">constexpr</span></code>)
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
Since C++17 (with <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>)
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Dist</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">myadvance</span><span class="special">(</span><span class="identifier">Iter</span><span class="special">&</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">Dist</span> <span class="identifier">n</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">Iter</span><span class="special">*</span> <span class="identifier">p</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">i</span><span class="special">;</span> <span class="comment">// So captures change actual pointed iterator value.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">call_if</span><span class="special"><</span><span class="identifier">is_random_access_iterator</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">></span> <span class="special">>(</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">([]</span> <span class="special">(</span><span class="keyword">auto</span> <span class="identifier">p</span><span class="special">,</span> <span class="keyword">auto</span> <span class="identifier">n</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// C++14 generic lambda.</span>
|
|
<span class="special">*</span><span class="identifier">p</span> <span class="special">+=</span> <span class="identifier">n</span><span class="special">;</span>
|
|
<span class="special">},</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span>
|
|
<span class="special">).</span><span class="keyword">template</span> <span class="identifier">else_if</span><span class="special"><</span><span class="identifier">is_bidirectional_iterator</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">></span> <span class="special">>(</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">([]</span> <span class="special">(</span><span class="keyword">auto</span> <span class="identifier">p</span><span class="special">,</span> <span class="keyword">auto</span> <span class="identifier">n</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">n</span> <span class="special">>=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">while</span><span class="special">(</span><span class="identifier">n</span><span class="special">--)</span> <span class="special">++*</span><span class="identifier">p</span><span class="special">;</span>
|
|
<span class="keyword">else</span> <span class="keyword">while</span><span class="special">(</span><span class="identifier">n</span><span class="special">++)</span> <span class="special">--*</span><span class="identifier">p</span><span class="special">;</span>
|
|
<span class="special">},</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span>
|
|
<span class="special">).</span><span class="keyword">template</span> <span class="identifier">else_if</span><span class="special"><</span><span class="identifier">is_input_iterator</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">></span> <span class="special">>(</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">([]</span> <span class="special">(</span><span class="keyword">auto</span> <span class="identifier">p</span><span class="special">,</span> <span class="keyword">auto</span> <span class="identifier">n</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">while</span><span class="special">(</span><span class="identifier">n</span><span class="special">--)</span> <span class="special">++*</span><span class="identifier">p</span><span class="special">;</span>
|
|
<span class="special">},</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">n</span><span class="special">)</span>
|
|
<span class="special">).</span><span class="identifier">else_</span><span class="special">(</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">([]</span> <span class="special">(</span><span class="keyword">auto</span> <span class="identifier">false_</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="identifier">false_</span><span class="special">,</span> <span class="string">"requires at least input iterator"</span><span class="special">);</span>
|
|
<span class="special">},</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">false_type</span><span class="special">())</span> <span class="comment">// Use constexpr value.</span>
|
|
<span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Dist</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">myadvance</span><span class="special">(</span><span class="identifier">Iter</span><span class="special">&</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">Dist</span> <span class="identifier">n</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">is_random_access_iterator</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">>::</span><span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">i</span> <span class="special">+=</span> <span class="identifier">n</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="keyword">else</span> <span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">is_bidirectional_iterator</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">>::</span><span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">n</span> <span class="special">>=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">while</span><span class="special">(</span><span class="identifier">n</span><span class="special">--)</span> <span class="special">++</span><span class="identifier">i</span><span class="special">;</span>
|
|
<span class="keyword">else</span> <span class="keyword">while</span><span class="special">(</span><span class="identifier">n</span><span class="special">++)</span> <span class="special">--</span><span class="identifier">i</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="keyword">else</span> <span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">is_input_iterator</span><span class="special"><</span><span class="identifier">Iter</span><span class="special">>::</span><span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">while</span><span class="special">(</span><span class="identifier">n</span><span class="special">--)</span> <span class="special">++</span><span class="identifier">p</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span>
|
|
<span class="keyword">static_assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">,</span> <span class="string">"requires at least input iterator"</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
This implementation is more concise, easier to read and maintain than the
|
|
usual implementation of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">advance</span></code>
|
|
that uses tag dispatching. Of course the implementation that uses C++17
|
|
<code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
is even more readable and concise.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.volatile_public_functions"></a><a class="link" href="extras.html#boost_contract.extras.volatile_public_functions" title="Volatile Public Functions">Volatile
|
|
Public Functions</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
This library allows to specify a different set of class invariants to check
|
|
for volatile public functions. These <span class="emphasis"><em>volatile class invariants</em></span>
|
|
are programmed in a public <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code> function, named <code class="computeroutput"><span class="identifier">invariant</span></code>,
|
|
taking no argument, and returning <code class="computeroutput"><span class="keyword">void</span></code>
|
|
(see <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870579312.html" title="Macro BOOST_CONTRACT_INVARIANT_FUNC">BOOST_CONTRACT_INVARIANT_FUNC</a></code>
|
|
to name the invariant function differently from <code class="computeroutput"><span class="identifier">invariant</span></code>
|
|
and <a class="link" href="advanced.html#boost_contract.advanced.access_specifiers" title="Access Specifiers">Access Specifiers</a>
|
|
to not have to declare it <code class="computeroutput"><span class="keyword">public</span></code>).
|
|
Classes that do no have invariants for their volatile public functions, simply
|
|
do not declare the <code class="computeroutput"><span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">volatile</span></code> function.
|
|
</p>
|
|
<p>
|
|
In general, <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
invariants work the same as <code class="computeroutput"><span class="keyword">const</span></code>
|
|
invariants (see <a class="link" href="tutorial.html#boost_contract.tutorial.class_invariants" title="Class Invariants">Class
|
|
Invariants</a>) with the only difference that <code class="computeroutput"><span class="keyword">volatile</span></code>
|
|
and <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
functions check <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
invariants while non-<code class="computeroutput"><span class="keyword">const</span></code> (i.e.,
|
|
neither <code class="computeroutput"><span class="keyword">const</span></code> nor <code class="computeroutput"><span class="keyword">volatile</span></code>) and <code class="computeroutput"><span class="keyword">const</span></code>
|
|
functions check <code class="computeroutput"><span class="keyword">const</span></code> invariants.
|
|
A given class can specify any combination of <code class="computeroutput"><span class="keyword">static</span></code>,
|
|
<code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>,
|
|
and <code class="computeroutput"><span class="keyword">const</span></code> invariant functions
|
|
(see <a class="link" href="tutorial.html#boost_contract.tutorial.class_invariants" title="Class Invariants">Class Invariants</a>):
|
|
<a href="#ftn.boost_contract.extras.volatile_public_functions.f0" class="footnote" name="boost_contract.extras.volatile_public_functions.f0"><sup class="footnote">[72]</sup></a>
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Constructors check <code class="computeroutput"><span class="keyword">static</span></code>
|
|
invariants at entry and exit (even if an exception is thrown), plus
|
|
<code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
and <code class="computeroutput"><span class="keyword">const</span></code> invariants in
|
|
that order at exit but only if no exception is thrown.
|
|
</li>
|
|
<li class="listitem">
|
|
Destructors check <code class="computeroutput"><span class="keyword">static</span></code>
|
|
invariants at entry and exit (even if an exception is thrown), plus
|
|
<code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
and <code class="computeroutput"><span class="keyword">const</span></code> invariants in
|
|
that order at entry (and at exit but only if an exception is thrown,
|
|
even is destructors should in general never throw in C++).
|
|
</li>
|
|
<li class="listitem">
|
|
Both non-<code class="computeroutput"><span class="keyword">const</span></code> and <code class="computeroutput"><span class="keyword">const</span></code> public functions check <code class="computeroutput"><span class="keyword">static</span></code> and <code class="computeroutput"><span class="keyword">const</span></code>
|
|
invariants at entry and at exit (even if an exception is thrown).
|
|
</li>
|
|
<li class="listitem">
|
|
Both <code class="computeroutput"><span class="keyword">volatile</span></code> and <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
public functions check <code class="computeroutput"><span class="keyword">static</span></code>
|
|
and <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
invariants at entry and at exit (even if an exception is thrown).
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
These rules ensure that volatile class invariants are correctly checked (see
|
|
<a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constructor_calls" title="Constructor Calls">Constructor
|
|
Calls</a>, <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.destructor_calls" title="Destructor Calls">Destructor
|
|
Calls</a>, and <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.public_function_calls" title="Public Function Calls">Public
|
|
Function Calls</a>). For example (see <a href="../../../example/features/volatile.cpp" target="_top"><code class="literal">volatile.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">u</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">static_invariant</span><span class="special">();</span> <span class="comment">// Static invariants.</span>
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">volatile</span><span class="special">;</span> <span class="comment">// Volatile invariants.</span>
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> <span class="comment">// Const invariants.</span>
|
|
|
|
<span class="identifier">u</span><span class="special">()</span> <span class="special">{</span> <span class="comment">// Check static, volatile, and const invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span><span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="special">~</span><span class="identifier">u</span><span class="special">()</span> <span class="special">{</span> <span class="comment">// Check static, volatile, and const invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">destructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">nc</span><span class="special">()</span> <span class="special">{</span> <span class="comment">// Check static and const invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">c</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="comment">// Check static and const invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">v</span><span class="special">()</span> <span class="keyword">volatile</span> <span class="special">{</span> <span class="comment">// Check static and volatile invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">cv</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">{</span> <span class="comment">// Check static and volatile invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">s</span><span class="special">()</span> <span class="special">{</span> <span class="comment">// Check static invariants only.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special"><</span><span class="identifier">u</span><span class="special">>();</span>
|
|
<span class="special">}</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
This library does not automatically check <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants for non-<code class="computeroutput"><span class="keyword">volatile</span></code> functions. However, if the contract
|
|
specifications require it, programmers can explicitly call the <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
invariant function from the <code class="computeroutput"><span class="keyword">const</span></code>
|
|
invariant function (preferably in that order to be consistent with the order
|
|
<code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
and <code class="computeroutput"><span class="keyword">const</span></code> invariants are checked
|
|
for constructors and destructors). That way all public functions, <code class="computeroutput"><span class="keyword">volatile</span></code> or not, will check <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
invariants (while only <code class="computeroutput"><span class="keyword">const</span></code>
|
|
and non-<code class="computeroutput"><span class="keyword">const</span></code> public functions
|
|
will check only <code class="computeroutput"><span class="keyword">const</span></code> invariants,
|
|
correctly so because the <code class="computeroutput"><span class="keyword">volatile</span></code>
|
|
qualifier shall not be stripped away): <a href="#ftn.boost_contract.extras.volatile_public_functions.f1" class="footnote" name="boost_contract.extras.volatile_public_functions.f1"><sup class="footnote">[73]</sup></a>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">u</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span> <span class="comment">// Volatile invariants.</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="keyword">const_cast</span><span class="special"><</span><span class="identifier">u</span> <span class="keyword">const</span> <span class="keyword">volatile</span><span class="special">*>(</span><span class="keyword">this</span><span class="special">)-></span><span class="identifier">invariant</span><span class="special">();</span> <span class="comment">// Call `const volatile` invariant function above.</span>
|
|
<span class="special">...</span> <span class="comment">// Other non-volatile invariants.</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="special">...</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
(As usual, private and protected functions do not check any invariant, not
|
|
even when they are <code class="computeroutput"><span class="keyword">volatile</span></code>
|
|
or <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>,
|
|
see <a class="link" href="advanced.html#boost_contract.advanced.private_and_protected_functions" title="Private and Protected Functions">Private
|
|
and Protected Functions</a>).
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.move_operations"></a><a class="link" href="extras.html#boost_contract.extras.move_operations" title="Move Operations">Move Operations</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
As with all public operations of a class, also public move operations should
|
|
maintain class invariants (see <a class="link" href="bibliography.html#Stroustrup13_anchor">[Stroustrup13]</a>,
|
|
p. 520). Specifically, C++ requires the following:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
The moved-from object can be copy assigned.
|
|
</li>
|
|
<li class="listitem">
|
|
The moved-from object can be move assigned.
|
|
</li>
|
|
<li class="listitem">
|
|
The moved-from object can be destroyed (if not for anything else, this
|
|
requires that class invariants are maintained by move operations because
|
|
the destructor of the moved-from object requires class invariants to
|
|
be satisfied at its entry, as always with destructors see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.destructor_calls" title="Destructor Calls">Destructor
|
|
Calls</a>).
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
Therefore, both the move constructor and the move assignment operator need
|
|
to maintain the class invariants of the moved-from object so their contracts
|
|
can be programmed using <code class="computeroutput"><a class="link" href="../boost/contract/constructor.html" title="Function template constructor">boost::contract::constructor</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
as usual. For example (see <a href="../../../example/features/move.cpp" target="_top"><code class="literal">move.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">circular_buffer</span> <span class="special">:</span>
|
|
<span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">circular_buffer</span><span class="special">></span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="keyword">if</span><span class="special">(!</span><span class="identifier">moved</span><span class="special">())</span> <span class="special">{</span> <span class="comment">// Do not check (some) invariants for moved-from objects.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">index</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">size</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
<span class="comment">// More invariants here that hold also for moved-from objects (e.g.,</span>
|
|
<span class="comment">// all assertions necessary to successfully destroy moved-from objects).</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Move constructor.</span>
|
|
<span class="comment">/* implicit */</span> <span class="identifier">circular_buffer</span><span class="special">(</span><span class="identifier">circular_buffer</span><span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">:</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">circular_buffer</span><span class="special">>([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(!</span><span class="identifier">other</span><span class="special">.</span><span class="identifier">moved</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(!</span><span class="identifier">moved</span><span class="special">());</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">other</span><span class="special">.</span><span class="identifier">moved</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">move</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">circular_buffer</span><span class="special">>(</span><span class="identifier">other</span><span class="special">));</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Move assignment.</span>
|
|
<span class="identifier">circular_buffer</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">circular_buffer</span><span class="special">&&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// Moved-from can be (move) assigned (so no pre `!moved()` here).</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(!</span><span class="identifier">other</span><span class="special">.</span><span class="identifier">moved</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(!</span><span class="identifier">moved</span><span class="special">());</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">other</span><span class="special">.</span><span class="identifier">moved</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">move</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special"><</span><span class="identifier">circular_buffer</span><span class="special">>(</span><span class="identifier">other</span><span class="special">));</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="special">~</span><span class="identifier">circular_buffer</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="comment">// Moved-from can always be destroyed (in fact no preconditions).</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">destructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">bool</span> <span class="identifier">moved</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">moved_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="keyword">bool</span> <span class="identifier">moved_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
This example assumes that it is possible to call the public function <code class="computeroutput"><span class="identifier">moved</span><span class="special">()</span></code>
|
|
on the moved-from object. <a href="#ftn.boost_contract.extras.move_operations.f0" class="footnote" name="boost_contract.extras.move_operations.f0"><sup class="footnote">[74]</sup></a>
|
|
</p>
|
|
<div class="note"><table border="0" summary="Note">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
|
<th align="left">Note</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
The default move constructor and move assignment operator generated by
|
|
C++ will not automatically check contracts. Therefore, unless the move
|
|
operations are not public or they have no preconditions, no postconditions,
|
|
and their class has no invariants, programmers should manually define them
|
|
using <code class="computeroutput"><a class="link" href="../boost/contract/constructor.html" title="Function template constructor">boost::contract::constructor</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/constructor_precondition.html" title="Class template constructor_precondition">boost::contract::constructor_precondition</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
instead of relying on their default implementations generated by C++. (Same
|
|
as for all other operations automatically implemented by C++.)
|
|
</p></td></tr>
|
|
</table></div>
|
|
<p>
|
|
As always, programmers can decide to not program contracts for a given type.
|
|
Specifically, they might decide to not program contracts for a class that
|
|
needs to be moved in order to skip the run-time overhead of checking contract
|
|
assertions to optimize performance (see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.benefits_and_costs" title="Benefits and Costs">Benefits
|
|
and Costs</a>).
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.unions"></a><a class="link" href="extras.html#boost_contract.extras.unions" title="Unions">Unions</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
In C++, a <code class="computeroutput"><span class="keyword">union</span></code> cannot have
|
|
virtual functions, bases classes, and cannot be used as a base class thus
|
|
subcontracting (<code class="computeroutput"><a class="link" href="../boost/contract/virtual_.html" title="Class virtual_">boost::contract::virtual_</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>,
|
|
etc.) do not apply to unions. Also a <code class="computeroutput"><span class="keyword">union</span></code>
|
|
cannot inherit from <code class="computeroutput"><a class="link" href="../boost/contract/constructor_precondition.html" title="Class template constructor_precondition">boost::contract::constructor_precondition</a></code>
|
|
(because it cannot have base classes) so such a class is used to declare
|
|
a local object that checks constructor preconditions (at the very beginning
|
|
of the constructor before old value copies and other contracts, see declaration
|
|
of <code class="computeroutput"><span class="identifier">pre</span></code> in the example below).
|
|
A part from that, this library is used as usual to program contracts for
|
|
unions. For example (see <a href="../../../example/features/union.cpp" target="_top"><code class="literal">union.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">union</span> <span class="identifier">positive</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">static_invariant</span><span class="special">()</span> <span class="special">{</span> <span class="comment">// Static class invariants.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">>=</span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="comment">// Class invariants.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">i_</span> <span class="special">></span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">d_</span> <span class="special">></span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Contracts for constructor, as usual but...</span>
|
|
<span class="keyword">explicit</span> <span class="identifier">positive</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// ...unions cannot have bases so constructor preconditions here.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">positive</span><span class="special">></span> <span class="identifier">pre</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special">></span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="special">});</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_instances</span> <span class="special">=</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">instances</span><span class="special">());</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_instances</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">i_</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
|
|
<span class="special">++</span><span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Contracts for destructor (as usual).</span>
|
|
<span class="special">~</span><span class="identifier">positive</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_instances</span> <span class="special">=</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">instances</span><span class="special">());</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">destructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_instances</span> <span class="special">-</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="special">--</span><span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Contracts for public function (as usual, but no virtual or override).</span>
|
|
<span class="keyword">void</span> <span class="identifier">get</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special">></span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="special">});</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">x</span> <span class="special">=</span> <span class="identifier">i_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Contracts for static public function (as usual).</span>
|
|
<span class="keyword">static</span> <span class="keyword">int</span> <span class="identifier">instances</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special"><</span><span class="identifier">positive</span><span class="special">>();</span>
|
|
<span class="keyword">return</span> <span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="keyword">int</span> <span class="identifier">i_</span><span class="special">;</span>
|
|
<span class="keyword">double</span> <span class="identifier">d_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.assertion_levels"></a><a class="link" href="extras.html#boost_contract.extras.assertion_levels" title="Assertion Levels">Assertion Levels</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
This library provides three predefined <span class="emphasis"><em>assertion levels</em></span>
|
|
that can be used to selectively disable assertions depending on their computational
|
|
complexity: <a href="#ftn.boost_contract.extras.assertion_levels.f0" class="footnote" name="boost_contract.extras.assertion_levels.f0"><sup class="footnote">[75]</sup></a>
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
is used to assert conditions that are not computationally expensive,
|
|
at least compared to the cost of executing the function body. These assertions
|
|
are always checked at run-time, they are not disabled.
|
|
</li>
|
|
<li class="listitem">
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123871181520.html" title="Macro BOOST_CONTRACT_ASSERT_AUDIT">BOOST_CONTRACT_ASSERT_AUDIT</a></code>
|
|
is used to assert conditions that are computationally expensive compared
|
|
to the cost of executing the function body. These assertions are not
|
|
checked at run-time unless programmers explicitly define <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_AUDITS.html" title="Macro BOOST_CONTRACT_AUDITS">BOOST_CONTRACT_AUDITS</a></code>
|
|
(undefined by default), but the conditions are always compiled and validated
|
|
syntactically (even when they are not actually evaluated and checked
|
|
at run-time).
|
|
</li>
|
|
<li class="listitem">
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123897980656.html" title="Macro BOOST_CONTRACT_ASSERT_AXIOM">BOOST_CONTRACT_ASSERT_AXIOM</a></code>
|
|
is used to assert conditions that are computationally prohibitive, at
|
|
least compared to the cost of executing the function body. These assertions
|
|
are never evaluated or checked at run-time, but the asserted conditions
|
|
are always compiled and validated syntactically so these assertions can
|
|
serve as formal comments in the code.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
In addition, <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_CHECK_AUDIT.html" title="Macro BOOST_CONTRACT_CHECK_AUDIT">BOOST_CONTRACT_CHECK_AUDIT</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_CHECK_AXIOM.html" title="Macro BOOST_CONTRACT_CHECK_AXIOM">BOOST_CONTRACT_CHECK_AXIOM</a></code>
|
|
are similar to <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123871181520.html" title="Macro BOOST_CONTRACT_ASSERT_AUDIT">BOOST_CONTRACT_ASSERT_AUDIT</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123897980656.html" title="Macro BOOST_CONTRACT_ASSERT_AXIOM">BOOST_CONTRACT_ASSERT_AXIOM</a></code>
|
|
but they are used to program audit and axiom levels for implementation checks
|
|
instead of assertions (see <a class="link" href="advanced.html#boost_contract.advanced.implementation_checks" title="Implementation Checks">Implementation
|
|
Checks</a>).
|
|
</p>
|
|
<p>
|
|
For example, <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123871181520.html" title="Macro BOOST_CONTRACT_ASSERT_AUDIT">BOOST_CONTRACT_ASSERT_AUDIT</a></code>
|
|
can be used to program computationally expensive assertions (see <a href="../../../example/features/assertion_level.cpp" target="_top"><code class="literal">assertion_level.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RandomIter</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="identifier">RandomIter</span> <span class="identifier">random_binary_search</span><span class="special">(</span><span class="identifier">RandomIter</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">RandomIter</span> <span class="identifier">last</span><span class="special">,</span>
|
|
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">RandomIter</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">function</span><span class="special">()</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">first</span> <span class="special"><=</span> <span class="identifier">last</span><span class="special">);</span> <span class="comment">// Default, not expensive.</span>
|
|
<span class="comment">// Expensive O(n) assertion (use AXIOM if prohibitive instead).</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT_AUDIT</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_sorted</span><span class="special">(</span><span class="identifier">first</span><span class="special">,</span> <span class="identifier">last</span><span class="special">));</span>
|
|
<span class="special">})</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">result</span> <span class="special">!=</span> <span class="identifier">last</span><span class="special">)</span> <span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(*</span><span class="identifier">result</span> <span class="special">==</span> <span class="identifier">value</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Similarly, <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_AUDITS.html" title="Macro BOOST_CONTRACT_AUDITS">BOOST_CONTRACT_AUDITS</a></code>
|
|
can be used to disable expensive old value copies and related assertions
|
|
that use them (see <a href="../../../example/features/assertion_level.cpp" target="_top"><code class="literal">assertion_level.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">vector</span> <span class="special">{</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">vector</span><span class="special">&</span> <span class="identifier">other</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="identifier">vector</span><span class="special">></span> <span class="identifier">old_me</span><span class="special">,</span> <span class="identifier">old_other</span><span class="special">;</span>
|
|
<span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_CONTRACT_AUDITS</span>
|
|
<span class="identifier">old_me</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(*</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="identifier">old_other</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">other</span><span class="special">);</span>
|
|
<span class="preprocessor">#endif</span> <span class="comment">// Else, skip old value copies...</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="comment">// ...and also skip related assertions.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT_AUDIT</span><span class="special">(*</span><span class="keyword">this</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_other</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT_AUDIT</span><span class="special">(</span><span class="identifier">other</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_me</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">vect_</span><span class="special">.</span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">other</span><span class="special">.</span><span class="identifier">vect_</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"> <span class="comment">/* ... */</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">vect_</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The condition passed to <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123897980656.html" title="Macro BOOST_CONTRACT_ASSERT_AXIOM">BOOST_CONTRACT_ASSERT_AXIOM</a></code>
|
|
is compiled but not actually evaluated at run-time so this macro can be used
|
|
to program computationally prohibitive assertions but also assertions that
|
|
cannot actually be programmed in C++ using functions that are declared but
|
|
left undefined. For example, (see <a href="../../../example/features/assertion_level.cpp" target="_top"><code class="literal">assertion_level.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// If valid iterator range (cannot implement in C++ but OK to use in AXIOM).</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Iter</span><span class="special">></span>
|
|
<span class="keyword">bool</span> <span class="identifier">valid</span><span class="special">(</span><span class="identifier">Iter</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">Iter</span> <span class="identifier">last</span><span class="special">);</span> <span class="comment">// Only declared, not actually defined.</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">vector</span> <span class="special">{</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">public</span><span class="special">:</span>
|
|
<span class="identifier">iterator</span> <span class="identifier">insert</span><span class="special">(</span><span class="identifier">iterator</span> <span class="identifier">where</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">iterator</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">></span> <span class="identifier">old_capacity</span> <span class="special">=</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">capacity</span><span class="special">()</span> <span class="special">>=</span> <span class="special">*</span><span class="identifier">old_capacity</span><span class="special">);</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">capacity</span><span class="special">()</span> <span class="special">></span> <span class="special">*</span><span class="identifier">old_capacity</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT_AXIOM</span><span class="special">(!</span><span class="identifier">valid</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">end</span><span class="special">()));</span>
|
|
<span class="special">}</span> <span class="keyword">else</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT_AXIOM</span><span class="special">(!</span><span class="identifier">valid</span><span class="special">(</span><span class="identifier">where</span><span class="special">,</span> <span class="identifier">end</span><span class="special">()));</span>
|
|
<span class="special">}</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">vect_</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">where</span><span class="special">,</span> <span class="identifier">value</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"> <span class="comment">/* ... */</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">vect_</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
In addition to the assertion levels predefined by this library, programmers
|
|
are free to define their own. For example, the following macro could be used
|
|
to program and selectively disable assertions that have exponential computational
|
|
complexity <code class="computeroutput"><span class="identifier">O</span><span class="special">(</span><span class="identifier">e</span><span class="special">^</span><span class="identifier">n</span><span class="special">)</span></code>:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#ifdef</span> <span class="identifier">NO_EXPONENTIALLY_COMPLEX_ASSERTIONS</span>
|
|
<span class="comment">// Following will compile but never actually evaluate `cond`.</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">EXP_ASSERTION</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span> <span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">true</span> <span class="special">||</span> <span class="special">(</span><span class="identifier">cond</span><span class="special">))</span>
|
|
<span class="preprocessor">#else</span>
|
|
<span class="comment">// Following will compile and also evaluate `cond`.</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">EXP_ASSERTION</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span> <span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="special">...</span>
|
|
|
|
<span class="identifier">EXP_ASSERTION</span><span class="special">(</span><code class="literal"><span class="emphasis"><em>some-exponentially-complex-boolean-condition</em></span></code><span class="special">);</span>
|
|
</pre>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.disable_contract_checking"></a><a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
|
Contract Checking</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
Checking contracts adds run-time overhead and can slow down program execution
|
|
(see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.benefits_and_costs" title="Benefits and Costs">Benefits
|
|
and Costs</a>). Therefore, programmers can define any combination of the
|
|
following macros (<code class="computeroutput"><span class="special">-</span><span class="identifier">D</span></code>
|
|
option in Clang and GCC, <code class="computeroutput"><span class="special">/</span><span class="identifier">D</span></code>
|
|
option in MSVC, etc.) to instruct this library to not check specific kind
|
|
of contract conditions at run-time:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870517808.html" title="Macro BOOST_CONTRACT_NO_PRECONDITIONS">BOOST_CONTRACT_NO_PRECONDITIONS</a></code>
|
|
to not check preconditions.
|
|
</li>
|
|
<li class="listitem">
|
|
Define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870511440.html" title="Macro BOOST_CONTRACT_NO_POSTCONDITIONS">BOOST_CONTRACT_NO_POSTCONDITIONS</a></code>
|
|
to not check postconditions.
|
|
</li>
|
|
<li class="listitem">
|
|
Define <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_EXCEPTS.html" title="Macro BOOST_CONTRACT_NO_EXCEPTS">BOOST_CONTRACT_NO_EXCEPTS</a></code>
|
|
to not check exception guarantees.
|
|
</li>
|
|
<li class="listitem">
|
|
Define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870492704.html" title="Macro BOOST_CONTRACT_NO_ENTRY_INVARIANTS">BOOST_CONTRACT_NO_ENTRY_INVARIANTS</a></code>
|
|
to not check class invariants at call entry.
|
|
</li>
|
|
<li class="listitem">
|
|
Define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870485088.html" title="Macro BOOST_CONTRACT_NO_EXIT_INVARIANTS">BOOST_CONTRACT_NO_EXIT_INVARIANTS</a></code>
|
|
to not check class invariants at call exit.
|
|
</li>
|
|
<li class="listitem">
|
|
Or, define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870477472.html" title="Macro BOOST_CONTRACT_NO_INVARIANTS">BOOST_CONTRACT_NO_INVARIANTS</a></code>
|
|
to not check class invariants at both call entry and exit. (This is provided
|
|
for convenience, it is equivalent to define both <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870492704.html" title="Macro BOOST_CONTRACT_NO_ENTRY_INVARIANTS">BOOST_CONTRACT_NO_ENTRY_INVARIANTS</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870485088.html" title="Macro BOOST_CONTRACT_NO_EXIT_INVARIANTS">BOOST_CONTRACT_NO_EXIT_INVARIANTS</a></code>.)
|
|
</li>
|
|
<li class="listitem">
|
|
Define <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>
|
|
to not perform implementation checks.
|
|
</li>
|
|
</ul></div>
|
|
<div class="note"><table border="0" summary="Note">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
|
<th align="left">Note</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
Old values can be used by both postconditions and exception guarantees
|
|
so it is necessary to define both <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870511440.html" title="Macro BOOST_CONTRACT_NO_POSTCONDITIONS">BOOST_CONTRACT_NO_POSTCONDITIONS</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_EXCEPTS.html" title="Macro BOOST_CONTRACT_NO_EXCEPTS">BOOST_CONTRACT_NO_EXCEPTS</a></code>
|
|
to disable old value copies.
|
|
</p></td></tr>
|
|
</table></div>
|
|
<p>
|
|
By default, none of these macros are defined so this library checks all contracts.
|
|
When these macros are defined by the user, the implementation code of this
|
|
library is internally optimized to minimize as much as possible any run-time
|
|
and compile-time overhead associated with checking and compiling contracts
|
|
(see <a class="link" href="extras.html#boost_contract.extras.disable_contract_compilation__macro_interface_" title="Disable Contract Compilation (Macro Interface)">Disable
|
|
Contract Compilation</a> for techniques to completely remove any run-time
|
|
and compile-time overhead associated with contract code).
|
|
</p>
|
|
<p>
|
|
For example, programmers could decide to check all contracts during early
|
|
development builds, but later check only preconditions and maybe entry invariants
|
|
for release builds by defining <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870511440.html" title="Macro BOOST_CONTRACT_NO_POSTCONDITIONS">BOOST_CONTRACT_NO_POSTCONDITIONS</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_EXCEPTS.html" title="Macro BOOST_CONTRACT_NO_EXCEPTS">BOOST_CONTRACT_NO_EXCEPTS</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870485088.html" title="Macro BOOST_CONTRACT_NO_EXIT_INVARIANTS">BOOST_CONTRACT_NO_EXIT_INVARIANTS</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.disable_contract_compilation__macro_interface_"></a><a class="link" href="extras.html#boost_contract.extras.disable_contract_compilation__macro_interface_" title="Disable Contract Compilation (Macro Interface)">Disable
|
|
Contract Compilation (Macro Interface)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
This library provides macros that can be used to completely disable compile-time
|
|
and run-time overhead introduced by contracts but at the cost of manually
|
|
programming <code class="computeroutput"><span class="preprocessor">#ifndef</span></code> statements
|
|
around contract code:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
This library defines <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870460880.html" title="Macro BOOST_CONTRACT_NO_CONSTRUCTORS">BOOST_CONTRACT_NO_CONSTRUCTORS</a></code>
|
|
when contract checking is disabled for constructors.
|
|
</li>
|
|
<li class="listitem">
|
|
This library defines <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870450032.html" title="Macro BOOST_CONTRACT_NO_DESTRUCTORS">BOOST_CONTRACT_NO_DESTRUCTORS</a></code>
|
|
when contract checking is disabled for destructors.
|
|
</li>
|
|
<li class="listitem">
|
|
This library defines <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870441776.html" title="Macro BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS">BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS</a></code>
|
|
when contract checking is disabled for public functions.
|
|
</li>
|
|
<li class="listitem">
|
|
This library defines <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870432592.html" title="Macro BOOST_CONTRACT_NO_FUNCTIONS">BOOST_CONTRACT_NO_FUNCTIONS</a></code>
|
|
when contract checking is disabled for (non-public and non-member) functions.
|
|
</li>
|
|
<li class="listitem">
|
|
This library defines <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_OLDS.html" title="Macro BOOST_CONTRACT_NO_OLDS">BOOST_CONTRACT_NO_OLDS</a></code>
|
|
when old value copies are disabled.
|
|
</li>
|
|
<li class="listitem">
|
|
This library defines <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_ALL.html" title="Macro BOOST_CONTRACT_NO_ALL">BOOST_CONTRACT_NO_ALL</a></code>
|
|
when all contracts above and also implementation checks (see <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>)
|
|
are disabled.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
These macros are not configuration macros and they should not be defined
|
|
directly by programmers (otherwise this library will generate a compile-time
|
|
error). Instead, these macros are automatically defined by this library when
|
|
programmers define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870517808.html" title="Macro BOOST_CONTRACT_NO_PRECONDITIONS">BOOST_CONTRACT_NO_PRECONDITIONS</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870511440.html" title="Macro BOOST_CONTRACT_NO_POSTCONDITIONS">BOOST_CONTRACT_NO_POSTCONDITIONS</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_EXCEPTS.html" title="Macro BOOST_CONTRACT_NO_EXCEPTS">BOOST_CONTRACT_NO_EXCEPTS</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870477472.html" title="Macro BOOST_CONTRACT_NO_INVARIANTS">BOOST_CONTRACT_NO_INVARIANTS</a></code>
|
|
(or <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870492704.html" title="Macro BOOST_CONTRACT_NO_ENTRY_INVARIANTS">BOOST_CONTRACT_NO_ENTRY_INVARIANTS</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870485088.html" title="Macro BOOST_CONTRACT_NO_EXIT_INVARIANTS">BOOST_CONTRACT_NO_EXIT_INVARIANTS</a></code>),
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>
|
|
(see <a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
|
Contract Checking</a>).
|
|
</p>
|
|
<p>
|
|
Alternatively, this library provides a macro-based interface <code class="computeroutput"><a class="link" href="../reference.html#header.boost.contract_macro_hpp" title="Header <boost/contract_macro.hpp>">boost/contract_macro.hpp</a></code> that
|
|
can also be used to completely disable compile-time and run-time overhead
|
|
introduced by contracts. For example, the following code shows how to use
|
|
both the macro interface and the <code class="computeroutput"><span class="preprocessor">#ifndef</span>
|
|
<span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code>
|
|
statements to completely disable compile-time and run-time overhead for non-member
|
|
function contracts (see <a href="../../../example/features/ifdef_macro.cpp" target="_top"><code class="literal">ifdef_macro.cpp</code></a>
|
|
and <a href="../../../example/features/ifdef.cpp" target="_top"><code class="literal">ifdef.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Macro Interface
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
<code class="computeroutput"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> Statements
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="comment">// Use macro interface to completely disable contract code compilation.</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">contract_macro</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">inc</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLD_PTR</span><span class="special">(</span><span class="keyword">int</span><span class="special">)(</span><span class="identifier">old_x</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_FUNCTION</span><span class="special">()</span>
|
|
<span class="identifier">BOOST_CONTRACT_PRECONDITION</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">max</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="identifier">BOOST_CONTRACT_POSTCONDITION</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">++;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="comment">// Use #ifdef to completely disable contract code compilation.</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">contract</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">config</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_ALL</span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">contract</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">inc</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_OLDS</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_x</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_FUNCTIONS</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">function</span><span class="special">()</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PRECONDITIONS</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">max</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_POSTCONDITIONS</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">++;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
The same can be done to disable contract code complication for private and
|
|
protected functions. The <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869551136.html" title="Macro BOOST_CONTRACT_OLD_PTR_IF_COPYABLE">BOOST_CONTRACT_OLD_PTR_IF_COPYABLE</a></code>
|
|
macro is provided to handle non-copyable old value types (similar to <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>).
|
|
For constructors, destructors, and public functions instead (see <a href="../../../example/features/ifdef_macro.cpp" target="_top"><code class="literal">ifdef_macro.cpp</code></a>
|
|
and <a href="../../../example/features/ifdef.cpp" target="_top"><code class="literal">ifdef.cpp</code></a>):
|
|
</p>
|
|
<div class="informaltable"><table class="table">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<thead><tr>
|
|
<th>
|
|
<p>
|
|
Macro Interface
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p>
|
|
<code class="computeroutput"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> Statements
|
|
</p>
|
|
</th>
|
|
</tr></thead>
|
|
<tbody><tr>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">class</span> <span class="identifier">integers</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">pushable</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span>
|
|
<span class="special">:</span>
|
|
<span class="comment">// Left in code (almost no overhead).</span>
|
|
<span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">integers</span><span class="special">>,</span>
|
|
<span class="identifier">BASES</span>
|
|
<span class="special">{</span>
|
|
<span class="comment">// Followings left in code (almost no overhead).</span>
|
|
<span class="keyword">friend</span> <span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">access</span><span class="special">;</span>
|
|
|
|
<span class="keyword">typedef</span> <span class="identifier">BOOST_CONTRACT_BASE_TYPES</span><span class="special">(</span><span class="identifier">BASES</span><span class="special">)</span> <span class="identifier">base_types</span><span class="special">;</span>
|
|
<span class="preprocessor">#undef</span> <span class="identifier">BASES</span>
|
|
|
|
<span class="identifier">BOOST_CONTRACT_INVARIANT</span><span class="special">({</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><=</span> <span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="identifier">integers</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">from</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">to</span><span class="special">)</span> <span class="special">:</span>
|
|
<span class="identifier">BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION</span><span class="special">(</span><span class="identifier">integers</span><span class="special">)([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">from</span> <span class="special"><=</span> <span class="identifier">to</span><span class="special">);</span>
|
|
<span class="special">}),</span>
|
|
<span class="identifier">vect_</span><span class="special">(</span><span class="identifier">to</span> <span class="special">-</span> <span class="identifier">from</span> <span class="special">+</span> <span class="number">1</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_CONSTRUCTOR</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="identifier">BOOST_CONTRACT_POSTCONDITION</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">int</span><span class="special">(</span><span class="identifier">size</span><span class="special">())</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">to</span> <span class="special">-</span> <span class="identifier">from</span> <span class="special">+</span> <span class="number">1</span><span class="special">));</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">from</span><span class="special">;</span> <span class="identifier">x</span> <span class="special"><=</span> <span class="identifier">to</span><span class="special">;</span> <span class="special">++</span><span class="identifier">x</span><span class="special">)</span> <span class="identifier">vect_</span><span class="special">.</span><span class="identifier">at</span><span class="special">(</span><span class="identifier">x</span> <span class="special">-</span> <span class="identifier">from</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">integers</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_DESTRUCTOR</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span> <span class="comment">// Check invariants.</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span>
|
|
<span class="keyword">int</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span> <span class="special">=</span> <span class="number">0</span> <span class="comment">// Left in code (almost no overhead).</span>
|
|
<span class="special">)</span> <span class="comment">/* override */</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLD_PTR</span><span class="special">(</span><span class="keyword">unsigned</span><span class="special">)(</span><span class="identifier">old_size</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_PUBLIC_FUNCTION_OVERRIDE</span><span class="special">(</span><span class="identifier">override_push_back</span><span class="special">)(</span>
|
|
<span class="identifier">v</span><span class="special">,</span> <span class="special">&</span><span class="identifier">integers</span><span class="special">::</span><span class="identifier">push_back</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span> <span class="identifier">x</span><span class="special">)</span>
|
|
<span class="identifier">BOOST_CONTRACT_PRECONDITION</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">max_size</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLD</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">old_size</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">size</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="identifier">BOOST_CONTRACT_POSTCONDITION</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="identifier">BOOST_CONTRACT_EXCEPT</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">vect_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">BOOST_CONTRACT_OVERRIDE</span><span class="special">(</span><span class="identifier">push_back</span><span class="special">)</span> <span class="comment">// Left in code (almost no overhead).</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p>
|
|
</p>
|
|
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">class</span> <span class="identifier">integers</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">pushable</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span>
|
|
<span class="special">:</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PRECONDITIONS</span>
|
|
<span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">integers</span><span class="special">>,</span> <span class="identifier">BASES</span>
|
|
<span class="preprocessor">#else</span>
|
|
<span class="identifier">BASES</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">{</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_ALL</span>
|
|
<span class="keyword">friend</span> <span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">access</span><span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">BOOST_CONTRACT_BASE_TYPES</span><span class="special">(</span><span class="identifier">BASES</span><span class="special">)</span> <span class="identifier">base_types</span><span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#undef</span> <span class="identifier">BASES</span>
|
|
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_INVARIANTS</span>
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><=</span> <span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="identifier">integers</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">from</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">to</span><span class="special">)</span> <span class="special">:</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PRECONDITIONS</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">integers</span><span class="special">>([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">from</span> <span class="special"><=</span> <span class="identifier">to</span><span class="special">);</span>
|
|
<span class="special">}),</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="identifier">vect_</span><span class="special">(</span><span class="identifier">to</span> <span class="special">-</span> <span class="identifier">from</span> <span class="special">+</span> <span class="number">1</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_CONSTRUCTORS</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_POSTCONDITIONS</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">int</span><span class="special">(</span><span class="identifier">size</span><span class="special">())</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">to</span> <span class="special">-</span> <span class="identifier">from</span> <span class="special">+</span> <span class="number">1</span><span class="special">));</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">from</span><span class="special">;</span> <span class="identifier">x</span> <span class="special"><=</span> <span class="identifier">to</span><span class="special">;</span> <span class="special">++</span><span class="identifier">x</span><span class="special">)</span> <span class="identifier">vect_</span><span class="special">.</span><span class="identifier">at</span><span class="special">(</span><span class="identifier">x</span> <span class="special">-</span> <span class="identifier">from</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">integers</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_DESTRUCTORS</span>
|
|
<span class="comment">// Check invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">destructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span>
|
|
<span class="keyword">int</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS</span>
|
|
<span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span> <span class="special">=</span> <span class="number">0</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">)</span> <span class="comment">/* override */</span> <span class="special">{</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_OLDS</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">></span> <span class="identifier">old_size</span><span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special"><</span>
|
|
<span class="identifier">override_push_back</span><span class="special">>(</span><span class="identifier">v</span><span class="special">,</span> <span class="special">&</span><span class="identifier">integers</span><span class="special">::</span><span class="identifier">push_back</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span> <span class="identifier">x</span><span class="special">)</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PRECONDITIONS</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">max_size</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_OLDS</span>
|
|
<span class="special">.</span><span class="identifier">old</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">old_size</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">size</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_POSTCONDITIONS</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_EXCEPTS</span>
|
|
<span class="special">.</span><span class="identifier">except</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="preprocessor">#endif</span>
|
|
<span class="special">;</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="identifier">vect_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS</span>
|
|
<span class="identifier">BOOST_CONTRACT_OVERRIDE</span><span class="special">(</span><span class="identifier">push_back</span><span class="special">)</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</td>
|
|
</tr></tbody>
|
|
</table></div>
|
|
<p>
|
|
Static and volatile class invariants can be programmed using <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869498768.html" title="Macro BOOST_CONTRACT_STATIC_INVARIANT">BOOST_CONTRACT_STATIC_INVARIANT</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869512624.html" title="Macro BOOST_CONTRACT_INVARIANT_VOLATILE">BOOST_CONTRACT_INVARIANT_VOLATILE</a></code>
|
|
respectively (these macros expand code equivalent to the <code class="computeroutput"><span class="keyword">static</span>
|
|
<span class="keyword">void</span> <span class="identifier">BOOST_CONTRACT_STATIC_INVARIANT_FUNC</span><span class="special">()</span></code> and <code class="computeroutput"><span class="keyword">void</span>
|
|
<span class="identifier">BOOST_CONTRACT_INVARIANT_FUNC</span><span class="special">()</span>
|
|
<span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
functions).
|
|
</p>
|
|
<p>
|
|
The macro interface is usually preferred because more concise and easier
|
|
to use than programming <code class="computeroutput"><span class="preprocessor">#ifndef</span>
|
|
<span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code>
|
|
statements by hand. However, C++ macros expand on a single line of code and
|
|
that can make compiler errors less useful when using the macro interface
|
|
plus all contract assertions within a given set of preconditions, postconditions,
|
|
exception guarantees, and class invariants will list the same line number
|
|
in error messages when assertions fail at run-time (but error messages still
|
|
list the assertion code and that should allow programmers to identify the
|
|
specific assertion that failed). Finally, the macro interface leaves a bit
|
|
of contract decorations in the code but that should add no measurable compile-time
|
|
and run-time overhead (specifically, extra <code class="computeroutput"><a class="link" href="../boost/contract/virtual_.html" title="Class virtual_">boost::contract::virtual_</a></code><code class="computeroutput"><span class="special">*</span></code> parameters, calls to <code class="computeroutput"><a class="link" href="../boost/contract/constructor_precondition.html" title="Class template constructor_precondition">boost::contract::constructor_precondition</a></code>
|
|
default constructor which does nothing, <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_BASE_TYPES.html" title="Macro BOOST_CONTRACT_BASE_TYPES">BOOST_CONTRACT_BASE_TYPES</a></code>
|
|
<code class="computeroutput"><span class="keyword">typedef</span></code>s, and <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code>
|
|
friendships are left in user code even when contracts are disabled).
|
|
</p>
|
|
<p>
|
|
Disabling contract as shown in <a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
|
Contract Checking</a> leaves the overhead of compiling contract code plus
|
|
some small run-time overhead due to the initialization of old value pointers
|
|
(even if those will be all null and no old value will be actually copied),
|
|
the calls to the contract functions used to initialize <code class="computeroutput"><a class="link" href="../boost/contract/check.html" title="Class check">boost::contract::check</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/constructor_precondition.html" title="Class template constructor_precondition">boost::contract::constructor_precondition</a></code>
|
|
(even if those calls will be internally optimized by this library to essentially
|
|
do nothing), etc. For truly performance critical code for which even such
|
|
small run-time overhead might not be acceptable, the macro interface (or
|
|
the <code class="computeroutput"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> statements) can be used to completely
|
|
disable compile-time and run-time overheads of contracts. However, for such
|
|
performance critical code even the overhead of checking simple preconditions
|
|
might be too much so it might be best to not program contracts at all.
|
|
</p>
|
|
<p>
|
|
Usually, if the overhead of checking preconditions and other assertions is
|
|
already considered acceptable for an application then the compile-time overhead
|
|
of contracts should not represent an issue and it should be sufficient to
|
|
be able to disable contract checking at run-time as indicated in <a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
|
Contract Checking</a> (without a real need to use the macro interface
|
|
or the <code class="computeroutput"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> statements in most cases).
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.separate_body_implementation"></a><a class="link" href="extras.html#boost_contract.extras.separate_body_implementation" title="Separate Body Implementation">Separate
|
|
Body Implementation</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
Contracts are part of the program specifications and not of its implementation
|
|
(see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.specifications_vs__implementation" title="Specifications vs. Implementation">Specifications
|
|
vs. Implementation</a>). However, this library uses function definitions
|
|
to program contracts so contract code appears together with the function
|
|
implementation code. This is not ideal (even if contracts programmed using
|
|
this library will always appear at the very beginning of the function definition
|
|
so programmers will easily be able to distinguish contract code from the
|
|
rest of the function implementation code so this might not be real limitation
|
|
in practise).
|
|
</p>
|
|
<p>
|
|
In some cases, it might be desirable to completely separate the contract
|
|
code from the function implementation code. For example, this could be necessary
|
|
for software that ships only header files and compiled object files to its
|
|
users. If contracts are programmed in function definitions that are compiled
|
|
in the object files, users will not be able to see the contract code to understand
|
|
semantics and usage of the functions (again, this might not be a real problem
|
|
in practice for example if contracts are already somehow extracted from the
|
|
source code by some toll and presented as part of the documentation of the
|
|
shipped software).
|
|
</p>
|
|
<p>
|
|
In any case, when it is truly important to separate contracts from function
|
|
implementation code, function implementations can be programmed in extra
|
|
<span class="emphasis"><em>body functions</em></span> (e.g., named <code class="computeroutput"><span class="special">...</span><span class="identifier">_body</span></code>) that are compiled in object files.
|
|
Function definitions that remain in header files instead will contain just
|
|
contract code followed by calls the extra body functions. This technique
|
|
allows to keep the contract code in header files while separating the implementation
|
|
code to object files. However, it adds the overhead of manually programming
|
|
an extra function declaration for the body function (plus the limitation
|
|
that constructor member initialization lists must be programmed in header
|
|
files because that is where constructors need to be defined to list constructor
|
|
contract code). <a href="#ftn.boost_contract.extras.separate_body_implementation.f0" class="footnote" name="boost_contract.extras.separate_body_implementation.f0"><sup class="footnote">[76]</sup></a>
|
|
</p>
|
|
<p>
|
|
For example, the following header file only contains function declarations,
|
|
contract code, and constructor member initializations, but it does not contain
|
|
the code implementing the function bodies (see <a href="../../../example/features/separate_body.hpp" target="_top"><code class="literal">separate_body.hpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">iarray</span> <span class="special">:</span>
|
|
<span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">iarray</span><span class="special">></span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><=</span> <span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">explicit</span> <span class="identifier">iarray</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">max</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">count</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="special">:</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">iarray</span><span class="special">>([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">count</span> <span class="special"><=</span> <span class="identifier">max</span><span class="special">);</span>
|
|
<span class="special">}),</span>
|
|
<span class="comment">// Still, member initializations must be here.</span>
|
|
<span class="identifier">values_</span><span class="special">(</span><span class="keyword">new</span> <span class="keyword">int</span><span class="special">[</span><span class="identifier">max</span><span class="special">]),</span>
|
|
<span class="identifier">capacity_</span><span class="special">(</span><span class="identifier">max</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">capacity</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">max</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">count</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
<span class="identifier">constructor_body</span><span class="special">(</span><span class="identifier">max</span><span class="special">,</span> <span class="identifier">count</span><span class="special">);</span> <span class="comment">// Separate constructor body impl.</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">iarray</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">destructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span> <span class="comment">// Inv.</span>
|
|
<span class="identifier">destructor_body</span><span class="special">();</span> <span class="comment">// Separate destructor body implementation.</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">value</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">></span> <span class="identifier">old_size</span> <span class="special">=</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">size</span><span class="special">());</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
<span class="identifier">push_back_body</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span> <span class="comment">// Separate member function body implementation.</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="comment">// Contracts in class declaration (above), but body implementations are not.</span>
|
|
<span class="keyword">void</span> <span class="identifier">constructor_body</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">max</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">count</span><span class="special">);</span>
|
|
<span class="keyword">void</span> <span class="identifier">destructor_body</span><span class="special">();</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back_body</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">value</span><span class="special">);</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Instead, the function bodies are implemented in a separate source file (see
|
|
<a href="../../../example/features/separate_body.cpp" target="_top"><code class="literal">separate_body.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">constructor_body</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">max</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">count</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">for</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">count</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">values_</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="keyword">int</span><span class="special">();</span>
|
|
<span class="identifier">size_</span> <span class="special">=</span> <span class="identifier">count</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">destructor_body</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">delete</span><span class="special">[]</span> <span class="identifier">values_</span><span class="special">;</span> <span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">push_back_body</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">value</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">values_</span><span class="special">[</span><span class="identifier">size_</span><span class="special">++]</span> <span class="special">=</span> <span class="identifier">value</span><span class="special">;</span> <span class="special">}</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The same technique can be used for non-member, private, protectee functions,
|
|
etc.
|
|
</p>
|
|
<div class="note"><table border="0" summary="Note">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
|
<th align="left">Note</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top">
|
|
<p>
|
|
When contracts are programmed only in <code class="literal">.cpp</code> files and
|
|
also all this library headers are <code class="computeroutput"><span class="preprocessor">#include</span></code>d
|
|
only from <code class="literal">.cpp</code> files, then these <code class="literal">.cpp</code>
|
|
files can be compiled disabling specific contract checking (for example,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870511440.html" title="Macro BOOST_CONTRACT_NO_POSTCONDITIONS">BOOST_CONTRACT_NO_POSTCONDITIONS</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_EXCEPTS.html" title="Macro BOOST_CONTRACT_NO_EXCEPTS">BOOST_CONTRACT_NO_EXCEPTS</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870485088.html" title="Macro BOOST_CONTRACT_NO_EXIT_INVARIANTS">BOOST_CONTRACT_NO_EXIT_INVARIANTS</a></code>,
|
|
see <a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
|
Contract Checking</a>). Then the code in these <code class="literal">.cpp</code>
|
|
files will always have such contract checking disabled even when linked
|
|
to some other user code that might have been compiled with a different
|
|
set of contracts disabled (i.e., a different set of <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> macros defined). This technique might
|
|
be useful to ship compiled object files (e.g., for a library) that will
|
|
never check some contracts (e.g., postconditions, exception guarantees,
|
|
and exit invariants) regardless of the definition of the <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code>
|
|
macros used to compile code that links against the shipped object files.
|
|
</p>
|
|
<p>
|
|
On the flip side, if contracts are programmed only in header files (e.g.,
|
|
using extra <code class="computeroutput"><span class="special">...</span><span class="identifier">_body</span></code>
|
|
functions as shown in this section) and this library headers are <code class="computeroutput"><span class="preprocessor">#include</span></code>d only in these header files
|
|
that are being shipped, then end users can enable or disables contract
|
|
checking of the shipped code by defining the <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> macros when they compile the shipped
|
|
header files as part of their code. This technique might be useful in other
|
|
situations when programmers that ship code want to leave it up the their
|
|
end users to decide which contracts of the shipped code should be checked
|
|
at run-time.
|
|
</p>
|
|
</td></tr>
|
|
</table></div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.no_lambda_functions__no_c__11_"></a><a class="link" href="extras.html#boost_contract.extras.no_lambda_functions__no_c__11_" title="No Lambda Functions (No C++11)">No
|
|
Lambda Functions (No C++11)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
This section shows how to use this library without C++11 lambda functions.
|
|
This has some advantages:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
It allows to use this library on compilers that do not support C++11
|
|
lambda functions (essentially most C++03 compilers with adequate support
|
|
for SFINAE can be used in that case, see <a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_" title="No Macros (and No Variadic Macros)">No
|
|
Macros</a> to also avoid using variadic macros).
|
|
</li>
|
|
<li class="listitem">
|
|
Contract functions (i.e., the <code class="computeroutput"><span class="special">...</span><span class="identifier">_precondition</span></code>, <code class="computeroutput"><span class="special">...</span><span class="identifier">_old</span></code>, and <code class="computeroutput"><span class="special">...</span><span class="identifier">_postcondition</span></code> functions in the example
|
|
below) can be programmed to fully enforce constant-correctness and other
|
|
contract requirements at compile-time (see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>).
|
|
<a href="#ftn.boost_contract.extras.no_lambda_functions__no_c__11_.f0" class="footnote" name="boost_contract.extras.no_lambda_functions__no_c__11_.f0"><sup class="footnote">[77]</sup></a>
|
|
</li>
|
|
<li class="listitem">
|
|
Code of the contract functions is separated from function body implementations
|
|
(see <a class="link" href="extras.html#boost_contract.extras.separate_body_implementation" title="Separate Body Implementation">Separate
|
|
Body Implementation</a>). <a href="#ftn.boost_contract.extras.no_lambda_functions__no_c__11_.f1" class="footnote" name="boost_contract.extras.no_lambda_functions__no_c__11_.f1"><sup class="footnote">[78]</sup></a>
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
However, not using C++11 lambda functions comes at the significant cost of
|
|
having to manually program the extra contract functions and related boiler-plate
|
|
code. For example (see <a href="../../../example/features/no_lambdas.hpp" target="_top"><code class="literal">no_lambdas.hpp</code></a>
|
|
and <a href="../../../example/features/no_lambdas.cpp" target="_top"><code class="literal">no_lambdas.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">iarray</span> <span class="special">:</span>
|
|
<span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">iarray</span><span class="special">></span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">static_invariant</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">>=</span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">invariant</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><=</span> <span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">explicit</span> <span class="identifier">iarray</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">max</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">count</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">constructor_precondition</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">const</span> <span class="identifier">max</span><span class="special">,</span>
|
|
<span class="keyword">unsigned</span> <span class="keyword">const</span> <span class="identifier">count</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">count</span> <span class="special"><=</span> <span class="identifier">max</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">constructor_old</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">>&</span>
|
|
<span class="identifier">old_instances</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">old_instances</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">instances</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">void</span> <span class="identifier">constructor_postcondition</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="keyword">const</span> <span class="identifier">max</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="keyword">const</span> <span class="identifier">count</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">old_instances</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">capacity</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">max</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">count</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_instances</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">iarray</span><span class="special">();</span>
|
|
<span class="keyword">void</span> <span class="identifier">destructor_old</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">>&</span> <span class="identifier">old_instances</span><span class="special">)</span>
|
|
<span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">old_instances</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">instances</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">static</span> <span class="keyword">void</span> <span class="identifier">destructor_postcondition</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="keyword">const</span>
|
|
<span class="identifier">old_instances</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_instances</span> <span class="special">-</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">value</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back_precondition</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special"><</span> <span class="identifier">capacity</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back_old</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">>&</span> <span class="identifier">old_size</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">old_size</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">size</span><span class="special">());</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back_postcondition</span><span class="special">(</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">old_size</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">unsigned</span> <span class="identifier">capacity</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
|
|
<span class="keyword">unsigned</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
|
|
|
|
<span class="keyword">static</span> <span class="keyword">int</span> <span class="identifier">instances</span><span class="special">();</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="keyword">int</span><span class="special">*</span> <span class="identifier">values_</span><span class="special">;</span>
|
|
<span class="keyword">unsigned</span> <span class="identifier">capacity_</span><span class="special">;</span>
|
|
<span class="keyword">unsigned</span> <span class="identifier">size_</span><span class="special">;</span>
|
|
<span class="keyword">static</span> <span class="keyword">int</span> <span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">iarray</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">max</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">count</span><span class="special">)</span> <span class="special">:</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">iarray</span><span class="special">>(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span>
|
|
<span class="special">&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special">,</span> <span class="identifier">max</span><span class="special">,</span> <span class="identifier">count</span><span class="special">)),</span>
|
|
<span class="identifier">values_</span><span class="special">(</span><span class="keyword">new</span> <span class="keyword">int</span><span class="special">[</span><span class="identifier">max</span><span class="special">]),</span> <span class="comment">// Member initializations can be here.</span>
|
|
<span class="identifier">capacity_</span><span class="special">(</span><span class="identifier">max</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_instances</span><span class="special">;</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">old</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">constructor_old</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">old_instances</span><span class="special">)))</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span>
|
|
<span class="special">&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">constructor_postcondition</span><span class="special">,</span>
|
|
<span class="keyword">this</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">max</span><span class="special">),</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">count</span><span class="special">),</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">old_instances</span><span class="special">)</span>
|
|
<span class="special">))</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">for</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">count</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">values_</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="keyword">int</span><span class="special">();</span>
|
|
<span class="identifier">size_</span> <span class="special">=</span> <span class="identifier">count</span><span class="special">;</span>
|
|
<span class="special">++</span><span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="identifier">iarray</span><span class="special">::~</span><span class="identifier">iarray</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_instances</span><span class="special">;</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">destructor</span><span class="special">(</span><span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">old</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">destructor_old</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">old_instances</span><span class="special">)))</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">destructor_postcondition</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">old_instances</span><span class="special">)))</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">delete</span><span class="special">[]</span> <span class="identifier">values_</span><span class="special">;</span>
|
|
<span class="special">--</span><span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">push_back</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">value</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">></span> <span class="identifier">old_size</span><span class="special">;</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">push_back_precondition</span><span class="special">,</span> <span class="keyword">this</span><span class="special">))</span>
|
|
<span class="special">.</span><span class="identifier">old</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">push_back_old</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">v</span><span class="special">),</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">old_size</span><span class="special">)))</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">iarray</span><span class="special">::</span><span class="identifier">push_back_postcondition</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">old_size</span><span class="special">)))</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">values_</span><span class="special">[</span><span class="identifier">size_</span><span class="special">++]</span> <span class="special">=</span> <span class="identifier">value</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">unsigned</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">capacity</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="comment">// Check invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">capacity_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">unsigned</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span>
|
|
<span class="comment">// Check invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="keyword">this</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">size_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">instances</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="comment">// Check static invariants.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special"><</span><span class="identifier">iarray</span><span class="special">>();</span>
|
|
<span class="keyword">return</span> <span class="identifier">instances_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">iarray</span><span class="special">::</span><span class="identifier">instances_</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
If programmers also want to fully enforce all contract programming constant-correctness
|
|
requirements at compile-time, they should follow these rules when programming
|
|
the contract functions (see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>):
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Precondition functions (i.e., the <code class="computeroutput"><span class="special">...</span><span class="identifier">_precondition</span></code> functions in the example
|
|
above) can take their arguments either by <code class="computeroutput"><span class="keyword">const</span></code>
|
|
value or by <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code>,
|
|
and when they are member functions they should be either <code class="computeroutput"><span class="keyword">static</span></code> or <code class="computeroutput"><span class="keyword">const</span></code>
|
|
functions.
|
|
</li>
|
|
<li class="listitem">
|
|
Postcondition functions (i.e., the <code class="computeroutput"><span class="special">...</span><span class="identifier">_postcondition</span></code> functions in the example
|
|
above) should take their arguments by <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code>, and when they are member functions
|
|
they should be either <code class="computeroutput"><span class="keyword">static</span></code>
|
|
or <code class="computeroutput"><span class="keyword">const</span></code> functions.
|
|
</li>
|
|
<li class="listitem">
|
|
Similarly, exception guarantee functions (not shown in the example above)
|
|
should take their arguments by <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code>, and when they are member functions
|
|
they should be either <code class="computeroutput"><span class="keyword">static</span></code>
|
|
or <code class="computeroutput"><span class="keyword">const</span></code> functions.
|
|
</li>
|
|
<li class="listitem">
|
|
Old value functions (i.e., the <code class="computeroutput"><span class="special">...</span><span class="identifier">_old</span></code> functions in the example above)
|
|
should take their arguments by <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code> a part from old value pointers that
|
|
should be taken by <code class="computeroutput"><span class="special">&</span></code>
|
|
(so only old value pointers can be modified), and when they are member
|
|
functions they should be either <code class="computeroutput"><span class="keyword">static</span></code>
|
|
or <code class="computeroutput"><span class="keyword">const</span></code> functions.
|
|
</li>
|
|
<li class="listitem">
|
|
Constructor precondition, old value, and exception guarantee functions
|
|
should be <code class="computeroutput"><span class="keyword">static</span></code> (because
|
|
there is no valid object <code class="computeroutput"><span class="keyword">this</span></code>
|
|
if the constructor body does not run successfully, see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constructor_calls" title="Constructor Calls">Constructor
|
|
Calls</a>).
|
|
</li>
|
|
<li class="listitem">
|
|
Destructor postcondition functions should be <code class="computeroutput"><span class="keyword">static</span></code>
|
|
(because there is no valid object <code class="computeroutput"><span class="keyword">this</span></code>
|
|
after the destructor body runs successfully, but exception guarantee
|
|
functions do not have to be <code class="computeroutput"><span class="keyword">static</span></code>
|
|
since the object <code class="computeroutput"><span class="keyword">this</span></code> is
|
|
still valid because the destructor body did not run successfully, see
|
|
<a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.destructor_calls" title="Destructor Calls">Destructor
|
|
Calls</a>).
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
Note that the extra contract functions also allow to keep the contract code
|
|
in the header file while all function bodies are implemented in a separate
|
|
source file (including the constructor member initialization list, that could
|
|
not be done with the techniques shown in <a class="link" href="extras.html#boost_contract.extras.separate_body_implementation" title="Separate Body Implementation">Separate
|
|
Body Implementation</a>). <a href="#ftn.boost_contract.extras.no_lambda_functions__no_c__11_.f2" class="footnote" name="boost_contract.extras.no_lambda_functions__no_c__11_.f2"><sup class="footnote">[79]</sup></a> Also note that the contract functions can always be declared
|
|
<code class="computeroutput"><span class="keyword">private</span></code> if programmers need
|
|
to exactly control the public members of the class (this was not done in
|
|
this example only for brevity).
|
|
</p>
|
|
<p>
|
|
The authors think this library is most useful when used together with C++11
|
|
lambda functions.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.extras.no_macros__and_no_variadic_macros_"></a><a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_" title="No Macros (and No Variadic Macros)">No
|
|
Macros (and No Variadic Macros)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
It is possible to specify contracts without using most of the macros provided
|
|
by this library and programming the related code manually instead (the only
|
|
macros that cannot be programmed manually are <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDES.html" title="Macro BOOST_CONTRACT_OVERRIDES">BOOST_CONTRACT_OVERRIDES</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>).
|
|
</p>
|
|
<div class="note"><table border="0" summary="Note">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
|
|
<th align="left">Note</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
Some of this library macros are variadic macros, others are not (see below).
|
|
Variadic macros were officially added to the language in C++11 but most
|
|
compilers have been supporting them as an extension for a long time, plus
|
|
all compilers that support C++11 lambda functions should also support C++11
|
|
variadic macros (and this library might rarely be used without the convenience
|
|
of C++11 lambda functions, see <a class="link" href="extras.html#boost_contract.extras.no_lambda_functions__no_c__11_" title="No Lambda Functions (No C++11)">No
|
|
Lambda Functions</a>). <a href="#ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f0" class="footnote" name="boost_contract.extras.no_macros__and_no_variadic_macros_.f0"><sup class="footnote">[80]</sup></a> Therefore, the rest of this section can be considered mainly
|
|
a curiosity because programmers should seldom, if ever, need to use this
|
|
library without using its macros.
|
|
</p></td></tr>
|
|
</table></div>
|
|
<h5>
|
|
<a name="boost_contract.extras.no_macros__and_no_variadic_macros_.h0"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.no_macros__and_no_variadic_macros_.overrides"></a></span><a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_.overrides">Overrides</a>
|
|
</h5>
|
|
<p>
|
|
As shown in <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a> and <a class="link" href="advanced.html#boost_contract.advanced.named_overrides" title="Named Overrides">Named
|
|
Overrides</a>, this library provides the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>
|
|
macros to program contracts for overriding public functions (see <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_MAX_ARGS.html" title="Macro BOOST_CONTRACT_MAX_ARGS">BOOST_CONTRACT_MAX_ARGS</a></code> for compilers
|
|
that do not support variadic templates). <a href="#ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f1" class="footnote" name="boost_contract.extras.no_macros__and_no_variadic_macros_.f1"><sup class="footnote">[81]</sup></a> These macro cannot be programmed manually but they are not variadic
|
|
macros (so programmers should be able to use them on any C++ compiler with
|
|
a sound support for SFINAE). <a href="#ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f2" class="footnote" name="boost_contract.extras.no_macros__and_no_variadic_macros_.f2"><sup class="footnote">[82]</sup></a> The <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDES.html" title="Macro BOOST_CONTRACT_OVERRIDES">BOOST_CONTRACT_OVERRIDES</a></code>
|
|
macro is a variadic macro instead but programmes can manually repeat the
|
|
non-variadic macro <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
for each overriding public function name on compilers that do not support
|
|
variadic macros.
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.extras.no_macros__and_no_variadic_macros_.h1"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.no_macros__and_no_variadic_macros_.assertions__not_variadic_"></a></span><a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_.assertions__not_variadic_">Assertions
|
|
(Not Variadic)</a>
|
|
</h5>
|
|
<p>
|
|
As shown in <a class="link" href="tutorial.html#boost_contract.tutorial.preconditions" title="Preconditions">Preconditions</a>,
|
|
<a class="link" href="tutorial.html#boost_contract.tutorial.postconditions" title="Postconditions">Postconditions</a>,
|
|
<a class="link" href="tutorial.html#boost_contract.tutorial.exception_guarantees" title="Exception Guarantees">Exception Guarantees</a>,
|
|
<a class="link" href="tutorial.html#boost_contract.tutorial.class_invariants" title="Class Invariants">Class Invariants</a>,
|
|
etc. this library provides the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
macro to assert contract conditions. This is not a variadic macro and programmers
|
|
should be able to use it on all C++ compilers. In any case, the invocation
|
|
<code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span></code> expands
|
|
to code equivalent to the following: <a href="#ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f3" class="footnote" name="boost_contract.extras.no_macros__and_no_variadic_macros_.f3"><sup class="footnote">[83]</sup></a>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">if</span><span class="special">(!(</span><span class="identifier">cond</span><span class="special">))</span> <span class="special">{</span>
|
|
<span class="keyword">throw</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">assertion_failure</span><span class="special">(</span><span class="identifier">__FILE__</span><span class="special">,</span> <span class="identifier">__LINE__</span><span class="special">,</span>
|
|
<span class="identifier">BOOST_PP_STRINGIZE</span><span class="special">(</span><span class="identifier">cond</span><span class="special">));</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
In fact, this library considers any exception thrown from within preconditions,
|
|
postconditions, exception guarantees, and class invariants as a contract
|
|
failure and reports it calling the related contract failure handler (<code class="computeroutput"><a class="link" href="../boost/contract/precondition_failure.html" title="Function precondition_failure">boost::contract::precondition_failure</a></code>,
|
|
etc.). If there is a need for it, programmers can always program contract
|
|
assertions that throw specific user-defined exceptions as follow (see <a class="link" href="advanced.html#boost_contract.advanced.throw_on_failures__and__noexcept__" title="Throw on Failures (and noexcept)">Throw
|
|
on Failures</a>):
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">if</span><span class="special">(!</span><span class="identifier">cond</span><span class="special">)</span> <span class="keyword">throw</span> <span class="identifier">exception_object</span><span class="special">;</span>
|
|
</pre>
|
|
<p>
|
|
However, using <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
is convenient because it always allows this library to show an informative
|
|
message in case of assertion failure containing the assertion code, file
|
|
name, line number, etc.
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123871181520.html" title="Macro BOOST_CONTRACT_ASSERT_AUDIT">BOOST_CONTRACT_ASSERT_AUDIT</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123897980656.html" title="Macro BOOST_CONTRACT_ASSERT_AXIOM">BOOST_CONTRACT_ASSERT_AXIOM</a></code>
|
|
macros are not variadic macros and programmers should be able to use them
|
|
on all C++ compilers. Their implementations are equivalent to the following:
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#ifdef</span> <span class="identifier">BOOST_CONTRACT_AUDITS</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BOOST_CONTRACT_ASSERT_AUDIT</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span>
|
|
<span class="preprocessor">#else</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BOOST_CONTRACT_ASSERT_AUDIT</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">true</span> <span class="special">||</span> <span class="special">(</span><span class="identifier">cond</span><span class="special">))</span>
|
|
<span class="preprocessor">#endif</span>
|
|
|
|
<span class="preprocessor">#define</span> <span class="identifier">BOOST_CONTRACT_ASSERT_AXIOM</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span> <span class="special">\</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">true</span> <span class="special">||</span> <span class="special">(</span><span class="identifier">cond</span><span class="special">))</span>
|
|
</pre>
|
|
<h5>
|
|
<a name="boost_contract.extras.no_macros__and_no_variadic_macros_.h2"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.no_macros__and_no_variadic_macros_.base_types__variadic_"></a></span><a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_.base_types__variadic_">Base
|
|
Types (Variadic)</a>
|
|
</h5>
|
|
<p>
|
|
As shown in <a class="link" href="tutorial.html#boost_contract.tutorial.base_classes__subcontracting_" title="Base Classes (Subcontracting)">Base
|
|
Classes</a>, this library provides the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_BASE_TYPES.html" title="Macro BOOST_CONTRACT_BASE_TYPES">BOOST_CONTRACT_BASE_TYPES</a></code>
|
|
variadic macro to declare the <code class="computeroutput"><span class="identifier">base_types</span></code>
|
|
member type that will expand to the list of all public bases for a derived
|
|
class. Programmers can also declare <code class="computeroutput"><span class="identifier">base_types</span></code>
|
|
without using <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_BASE_TYPES.html" title="Macro BOOST_CONTRACT_BASE_TYPES">BOOST_CONTRACT_BASE_TYPES</a></code>
|
|
at the cost of writing a bit more code and increase maintenance efforts.
|
|
For example (see <a href="../../../example/features/base_types_no_macro.cpp" target="_top"><code class="literal">base_types_no_macro.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">mpl</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
|
|
<span class="keyword">class</span> <span class="identifier">chars</span> <span class="special">:</span>
|
|
<span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">constructor_precondition</span><span class="special"><</span><span class="identifier">chars</span><span class="special">>,</span>
|
|
<span class="keyword">public</span> <span class="identifier">unique_chars</span><span class="special">,</span>
|
|
<span class="keyword">public</span> <span class="keyword">virtual</span> <span class="identifier">pushable</span><span class="special"><</span><span class="keyword">char</span><span class="special">>,</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">protected</span> <span class="identifier">has_size</span><span class="special">,</span>
|
|
<span class="keyword">private</span> <span class="identifier">has_empty</span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="comment">// Program `base_types` without macros (list only public bases).</span>
|
|
<span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">unique_chars</span><span class="special">,</span> <span class="identifier">pushable</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="special">></span> <span class="identifier">base_types</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput"><span class="identifier">base_types</span></code> member type
|
|
must be a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span></code>
|
|
which must list <span class="emphasis"><em>all and only</em></span> <code class="computeroutput"><span class="keyword">public</span></code>
|
|
base classes (because only public bases subcontract, see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.function_calls" title="Function Calls">Function
|
|
Calls</a>), and in the same order these public base classes appear in
|
|
the derived class inheritance list. If the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_BASE_TYPES.html" title="Macro BOOST_CONTRACT_BASE_TYPES">BOOST_CONTRACT_BASE_TYPES</a></code>
|
|
macro is not used, it is the responsibility of the programmers to maintain
|
|
the correct list of bases in the <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">mpl</span><span class="special">::</span><span class="identifier">vector</span></code> each time the derived class inheritance
|
|
list changes (this might significantly complicate maintenance).
|
|
</p>
|
|
<p>
|
|
In general, it is recommended to use the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_BASE_TYPES.html" title="Macro BOOST_CONTRACT_BASE_TYPES">BOOST_CONTRACT_BASE_TYPES</a></code>
|
|
macro whenever possible.
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.extras.no_macros__and_no_variadic_macros_.h3"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.no_macros__and_no_variadic_macros_.old_values__variadic_"></a></span><a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_.old_values__variadic_">Old
|
|
Values (Variadic)</a>
|
|
</h5>
|
|
<p>
|
|
As shown in <a class="link" href="tutorial.html#boost_contract.tutorial.old_values" title="Old Values">Old Values</a>,
|
|
this library provides the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
variadic macro to assign old value copies. Programmers can also assign old
|
|
values without using <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
at the cost of writing a bit more code manually. For example (see <a href="../../../example/features/old_no_macro.cpp" target="_top"><code class="literal">old_no_macro.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">vector</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">virtual_</span><span class="special">*</span> <span class="identifier">v</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// Program old value instead of using `OLD(size())` macro.</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">></span> <span class="identifier">old_size</span> <span class="special">=</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">make_old</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">copy_old</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">?</span>
|
|
<span class="identifier">size</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">null_old</span><span class="special">())</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">public_function</span><span class="special">(</span><span class="identifier">v</span><span class="special">,</span> <span class="keyword">this</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_size</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">vect_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The ternary operator <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">copy_old</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span>
|
|
<span class="special">?</span> <span class="identifier">size</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">null_old</span><span class="special">()</span></code> must be used here to avoid evaluating and
|
|
copying the old value expression <code class="computeroutput"><span class="identifier">size</span><span class="special">()</span></code> when <code class="computeroutput"><a class="link" href="../boost/contract/copy_old_idm45123869813440.html" title="Function copy_old">boost::contract::copy_old</a></code>
|
|
returns <code class="computeroutput"><span class="keyword">false</span></code> (because old values
|
|
are not being copied when postcondition and exception guarantees checking
|
|
is disabled at run-time, an overridden virtual function call is not checking
|
|
postconditions or exception guarantees yet, etc.). The enclosing <code class="computeroutput"><a class="link" href="../boost/contract/make_old_idm45123869837456.html" title="Function make_old">boost::contract::make_old</a></code>
|
|
copies the old value expression and creates an old value pointer. Otherwise,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/null_old.html" title="Function null_old">boost::contract::null_old</a></code>
|
|
indicates that a null old value pointer should be created.
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput"><a class="link" href="../boost/contract/make_old_idm45123869837456.html" title="Function make_old">boost::contract::make_old</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/copy_old_idm45123869813440.html" title="Function copy_old">boost::contract::copy_old</a></code>
|
|
functions are used exactly as shown above but without the extra <code class="computeroutput"><span class="identifier">v</span></code> parameter when they are called from within
|
|
non-virtual functions (see <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>). The old value pointer returned by <code class="computeroutput"><a class="link" href="../boost/contract/make_old_idm45123869837456.html" title="Function make_old">boost::contract::make_old</a></code>
|
|
can be assigned to either <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
|
or <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr_if_copyable.html" title="Class template old_ptr_if_copyable">boost::contract::old_ptr_if_copyable</a></code>
|
|
(see <a class="link" href="extras.html#boost_contract.extras.old_value_requirements__templates_" title="Old Value Requirements (Templates)">Old
|
|
Value Requirements</a>).
|
|
</p>
|
|
<p>
|
|
In general, it is recommended to use the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
macro whenever possible.
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.extras.no_macros__and_no_variadic_macros_.h4"></a>
|
|
<span class="phrase"><a name="boost_contract.extras.no_macros__and_no_variadic_macros_.macro_interface__variadic_"></a></span><a class="link" href="extras.html#boost_contract.extras.no_macros__and_no_variadic_macros_.macro_interface__variadic_">Macro
|
|
Interface (Variadic)</a>
|
|
</h5>
|
|
<p>
|
|
Almost all macros defined in <code class="computeroutput"><a class="link" href="../reference.html#header.boost.contract_macro_hpp" title="Header <boost/contract_macro.hpp>">boost/contract_macro.hpp</a></code>
|
|
are variadic macros. On compilers that do not support variadic macros, programmers
|
|
can manually disable contract code compilation using <code class="computeroutput"><span class="preprocessor">#ifndef</span>
|
|
<span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code>
|
|
statements as shown in <a class="link" href="extras.html#boost_contract.extras.disable_contract_compilation__macro_interface_" title="Disable Contract Compilation (Macro Interface)">Disable
|
|
Contract Compilation</a>.
|
|
</p>
|
|
</div>
|
|
<div class="footnotes">
|
|
<br><hr style="width:100; text-align:left;margin-left: 0">
|
|
<div id="ftn.boost_contract.extras.old_value_requirements__templates_.f0" class="footnote">
|
|
<p><a href="#boost_contract.extras.old_value_requirements__templates_.f0" class="para"><sup class="para">[68] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> <a class="link" href="bibliography.html#N1962_anchor">[N1962]</a>
|
|
and other proposals to add contracts to C++ do not provide a mechanism
|
|
to selectively disable copies only for old value types that are not copy
|
|
constructible. However, this library provides such a mechanism to allow
|
|
to program contracts for template code without necessarily adding extra
|
|
copy constructible type requirements that would not be present if it were
|
|
not for copying the old values (so compiling the code with and without
|
|
contracts will not necessarily alter the type requirements of the program).
|
|
Something similar could be achieved combing C++17 <code class="computeroutput"><span class="keyword">if</span>
|
|
<span class="keyword">constexpr</span></code> with <a class="link" href="bibliography.html#N1962_anchor">[N1962]</a>
|
|
or <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a> so that old value expressions
|
|
within template code could be guarded by <code class="computeroutput"><span class="keyword">if</span>
|
|
<span class="keyword">constexpr</span></code> statements checking if
|
|
the old value types are copyable or not. For example, assuming old values
|
|
are added to <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a> (using the <code class="computeroutput"><span class="identifier">oldof</span><span class="special">(...)</span></code>
|
|
syntax) and that C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code> can be used within <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a>
|
|
contracts:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">void</span> <span class="identifier">offset</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">count</span><span class="special">)</span>
|
|
<span class="special">[[</span><span class="identifier">ensures</span><span class="special">:</span> <span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_copy_constructible</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value</span><span class="special">)</span> <span class="identifier">x</span> <span class="special">==</span> <span class="identifier">oldof</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">+</span> <span class="identifier">count</span><span class="special">]]</span>
|
|
<span class="special">...</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</div>
|
|
<div id="ftn.boost_contract.extras.assertion_requirements__templates_.f0" class="footnote">
|
|
<p><a href="#boost_contract.extras.assertion_requirements__templates_.f0" class="para"><sup class="para">[69] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> <a class="link" href="bibliography.html#N1962_anchor">[N1962]</a>
|
|
and other proposals to add contracts to C++ do not provide a mechanism
|
|
to selectively disable assertions based on their type requirements. However,
|
|
this library provides such a mechanism to allow to program contracts for
|
|
template code without necessarily adding extra type requirements that would
|
|
not be present if it was not for the contracts (so compiling the code with
|
|
and without contracts will not necessarily alter the type requirements
|
|
of the program). Something similar could be achieved combing C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
with <a class="link" href="bibliography.html#N1962_anchor">[N1962]</a> or <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a>
|
|
so that contract assertions within template code could be guarded by <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
statements checking related type requirements (<a class="link" href="bibliography.html#N1962_anchor">[N1962]</a>
|
|
already supports <code class="computeroutput"><span class="keyword">if</span></code> statements
|
|
under the name of <span class="emphasis"><em>select assertions</em></span>, <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a>
|
|
does not so probably <code class="computeroutput"><span class="keyword">if</span></code> statements
|
|
should be added to <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a> as well).
|
|
For example, assuming old values are added to <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a>
|
|
(using the <code class="computeroutput"><span class="identifier">oldof</span><span class="special">(...)</span></code>
|
|
syntax) and that C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code> can be used within <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a>
|
|
contracts:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">vector</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">void</span> <span class="identifier">push_back</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">value</span><span class="special">)</span>
|
|
<span class="special">[[</span><span class="identifier">ensures</span><span class="special">:</span> <span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">value</span><span class="special">)</span> <span class="identifier">back</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">value</span><span class="special">]]</span>
|
|
<span class="special">...</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</div>
|
|
<div id="ftn.boost_contract.extras.assertion_requirements__templates_.f1" class="footnote"><p><a href="#boost_contract.extras.assertion_requirements__templates_.f1" class="para"><sup class="para">[70] </sup></a>
|
|
For optimization reasons, the internal implementation of <code class="computeroutput"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code>
|
|
does not actually use <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code>.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.assertion_requirements__templates_.f2" class="footnote"><p><a href="#boost_contract.extras.assertion_requirements__templates_.f2" class="para"><sup class="para">[71] </sup></a>
|
|
Boost.Hana (<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">hana</span><span class="special">::</span><span class="identifier">if_</span></code>) and probably other approaches can
|
|
also be used together with generic lambdas to emulate C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
|
on C++14 compilers.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.volatile_public_functions.f0" class="footnote"><p><a href="#boost_contract.extras.volatile_public_functions.f0" class="para"><sup class="para">[72] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> Constructors and destructors
|
|
check <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
and <code class="computeroutput"><span class="keyword">const</span></code> invariants in that
|
|
order because the qualifier that can be applied to more calls is checked
|
|
first (note that <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>
|
|
calls can be made on any object while <code class="computeroutput"><span class="keyword">const</span></code>
|
|
calls cannot be made on <code class="computeroutput"><span class="keyword">volatile</span></code>
|
|
objects, in that sense the <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> qualifier can be applied
|
|
to more calls than <code class="computeroutput"><span class="keyword">const</span></code> alone
|
|
can). This is consistent with <code class="computeroutput"><span class="keyword">static</span></code>
|
|
class invariants that are checked even before <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants (the <code class="computeroutput"><span class="keyword">static</span></code> classifier can be applied to even
|
|
more calls than <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>,
|
|
in fact an object is not even needed to make static calls).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.volatile_public_functions.f1" class="footnote"><p><a href="#boost_contract.extras.volatile_public_functions.f1" class="para"><sup class="para">[73] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> Note that while all public
|
|
functions can be made to check <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants, it is never
|
|
possible to make volatile public functions check <code class="computeroutput"><span class="keyword">const</span></code>
|
|
non-volatile invariants. That is because both <code class="computeroutput"><span class="keyword">const</span></code>
|
|
and <code class="computeroutput"><span class="keyword">volatile</span></code> can always be
|
|
added but never stripped in C++ (a part from forcefully via <code class="computeroutput"><span class="keyword">const_cast</span></code>) but <code class="computeroutput"><span class="keyword">const</span></code>
|
|
is always automatically added by this library in order to enforce contract
|
|
constant-correctness (see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>).
|
|
That said, it would be too stringent for this library to also automatically
|
|
add <code class="computeroutput"><span class="keyword">volatile</span></code> and require all
|
|
functions to check <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code> (not just <code class="computeroutput"><span class="keyword">const</span></code>)
|
|
invariants because only <code class="computeroutput"><span class="keyword">volatile</span></code>
|
|
members can be accessed from <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants so there could
|
|
be many <code class="computeroutput"><span class="keyword">const</span></code> (but not <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>)
|
|
members that are accessible from <code class="computeroutput"><span class="keyword">const</span></code>
|
|
invariants but not from <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code> invariants. To avoid this confusion,
|
|
this library has chosen to draw a clear dichotomy between <code class="computeroutput"><span class="keyword">const</span></code> and <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants so that only
|
|
volatile public functions check <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants and only non-volatile
|
|
public functions check <code class="computeroutput"><span class="keyword">const</span></code>
|
|
(but not <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code>)
|
|
invariants. This is simple and should serve most cases. If programmers
|
|
need non-volatile public functions to also check <code class="computeroutput"><span class="keyword">const</span>
|
|
<span class="keyword">volatile</span></code> invariants, they can explicitly
|
|
do so by calling the <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">volatile</span></code> invariant function from the <code class="computeroutput"><span class="keyword">const</span></code> invariant function as shown in this
|
|
documentation.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.move_operations.f0" class="footnote"><p><a href="#boost_contract.extras.move_operations.f0" class="para"><sup class="para">[74] </sup></a>
|
|
In this example, the <code class="computeroutput"><span class="identifier">moved</span><span class="special">()</span></code> function is simple enough that programmers
|
|
could decide to not even call <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
from it. However, calling <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
from <code class="computeroutput"><span class="identifier">moved</span><span class="special">()</span></code>
|
|
has no negative impact a part from run-time overhead because this library
|
|
already automatically disables contract checking while checking other contracts
|
|
(so this call will not cause infinite recursion).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.assertion_levels.f0" class="footnote"><p><a href="#boost_contract.extras.assertion_levels.f0" class="para"><sup class="para">[75] </sup></a>
|
|
The assertion levels predefined by this library are similar to the default,
|
|
audit, and axiom levels proposed in <a class="link" href="bibliography.html#P0380_anchor">[P0380]</a>.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.separate_body_implementation.f0" class="footnote">
|
|
<p><a href="#boost_contract.extras.separate_body_implementation.f0" class="para"><sup class="para">[76] </sup></a>
|
|
When used as default parameter values, lambda functions allow to program
|
|
code statements within function declarations. However, these lambadas cannot
|
|
be effectively used to program contracts because the C++11 standard does
|
|
not allow them to capture any variable (it would be not at all obvious
|
|
how to correctly define the semantics of such captures). For example, the
|
|
following code does not compile:
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Specifications (in declaration).</span>
|
|
<span class="keyword">int</span> <span class="identifier">inc</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span>
|
|
<span class="comment">// Error: Lambdas in default parameters cannot capture `this`, `x`, or any other variable.</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="keyword">void</span> <span class="special">()></span> <span class="identifier">pre</span> <span class="special">=</span> <span class="special">[&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special"><</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">max</span><span class="special">());</span>
|
|
<span class="special">},</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="keyword">void</span> <span class="special">(</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">&,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="keyword">const</span><span class="special">&)></span> <span class="identifier">post</span>
|
|
<span class="special">=</span> <span class="special">[&]</span> <span class="special">(</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">result</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">old_x</span><span class="special">)</span>
|
|
<span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">x</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">result</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_x</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="comment">// Implementation (in definition).</span>
|
|
<span class="keyword">int</span> <span class="identifier">inc</span><span class="special">(</span><span class="keyword">int</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="keyword">void</span> <span class="special">()></span> <span class="identifier">pre</span><span class="special">,</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="keyword">void</span> <span class="special">(</span><span class="keyword">int</span> <span class="keyword">const</span><span class="special">&,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="keyword">const</span><span class="special">&)></span> <span class="identifier">post</span>
|
|
<span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">int</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_x</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">check</span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">function</span><span class="special">()</span>
|
|
<span class="special">.</span><span class="identifier">precondition</span><span class="special">(</span><span class="identifier">pre</span><span class="special">)</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span><span class="identifier">post</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">result</span><span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">cref</span><span class="special">(</span><span class="identifier">old_x</span><span class="special">)))</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">++;</span> <span class="comment">// Function body.</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
In any case, even if the above code compiled, it would require significant
|
|
boiler-plate code to bind return and old values.
|
|
</p>
|
|
</div>
|
|
<div id="ftn.boost_contract.extras.no_lambda_functions__no_c__11_.f0" class="footnote"><p><a href="#boost_contract.extras.no_lambda_functions__no_c__11_.f0" class="para"><sup class="para">[77] </sup></a>
|
|
If C++ allowed lambda functions to capture variables by constant reference
|
|
(for example using the syntax <code class="computeroutput"><span class="special">[</span><span class="keyword">const</span><span class="special">&]</span>
|
|
<span class="special">{</span> <span class="special">...</span>
|
|
<span class="special">}</span></code> and <code class="computeroutput"><span class="special">[</span><span class="keyword">const</span><span class="special">&</span>
|
|
</code><code class="literal"><span class="emphasis"><em>variable-name</em></span></code><code class="computeroutput"><span class="special">]</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span></code>,
|
|
see <a href="https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/0UKQw9eo3N0" target="_top">https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/0UKQw9eo3N0</a>)
|
|
also lambdas could be used to program contract functors that fully
|
|
enforce <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>
|
|
at compile-time. Note that C++11 lambdas allow to capture variables
|
|
by value (using <code class="computeroutput"><span class="special">[=]</span> <span class="special">{</span>
|
|
<span class="special">...</span> <span class="special">}</span></code>
|
|
and <code class="computeroutput"><span class="special">[</span></code><code class="literal"><span class="emphasis"><em>variable-name</em></span></code><code class="computeroutput"><span class="special">]</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span></code>),
|
|
these value captures are <code class="computeroutput"><span class="keyword">const</span></code>
|
|
(unless the lambda is explicitly declared <code class="computeroutput"><span class="keyword">mutable</span></code>)
|
|
but they are not suitable to program postconditions and exception guarantees
|
|
using this library (because those require capturing by reference, see
|
|
<a class="link" href="tutorial.html#boost_contract.tutorial.postconditions" title="Postconditions">Postconditions</a>
|
|
and <a class="link" href="tutorial.html#boost_contract.tutorial.exception_guarantees" title="Exception Guarantees">Exception
|
|
Guarantees</a>), plus they introduce a copy of the captured value
|
|
that might be too expensive in general and therefore not suitable for
|
|
preconditions either.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.no_lambda_functions__no_c__11_.f1" class="footnote"><p><a href="#boost_contract.extras.no_lambda_functions__no_c__11_.f1" class="para"><sup class="para">[78] </sup></a>
|
|
Alternatively, on compilers that do not support C++11 lambda functions,
|
|
<a href="http://www.boost.org/doc/libs/release/libs/local_function/doc/html/index.html" target="_top">Boost.LocalFunction</a>
|
|
could be used to program the contract functors still within the function
|
|
definitions (for example, see <a href="../../../example/features/no_lambdas_local_func.cpp" target="_top"><code class="literal">no_lambda_local_func.cpp</code></a>).
|
|
In general, such a code is less verbose than the example shown in this
|
|
section that uses contract functions programmed outside of the original
|
|
function definitions (about 30% less lines of code) but the contract
|
|
code is hard to read. Other libraries could also be used to program
|
|
the contract functors without C++11 lambda functions (Boost.Lambda,
|
|
Boost.Fusion, etc.) but again all these techniques will result in contract
|
|
code either more verbose, or harder to read and maintain than the code
|
|
that uses C++11 lambda functions.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.no_lambda_functions__no_c__11_.f2" class="footnote"><p><a href="#boost_contract.extras.no_lambda_functions__no_c__11_.f2" class="para"><sup class="para">[79] </sup></a>
|
|
In this example, <code class="computeroutput"><span class="identifier">bind</span></code> was
|
|
used to generate nullary functors from the contract functions. As always
|
|
with <code class="computeroutput"><span class="identifier">bind</span></code>, <code class="computeroutput"><span class="identifier">cref</span></code> and <code class="computeroutput"><span class="identifier">ref</span></code>
|
|
must be used to bind arguments by <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code> and <code class="computeroutput"><span class="special">&</span></code>
|
|
respectively, plus it might be necessary to explicitly <code class="computeroutput"><span class="keyword">static_cast</span></code>
|
|
the function pointer passed to <code class="computeroutput"><span class="identifier">bind</span></code>
|
|
for overloaded functions.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f0" class="footnote"><p><a href="#boost_contract.extras.no_macros__and_no_variadic_macros_.f0" class="para"><sup class="para">[80] </sup></a>
|
|
Compilation times of this library were measured to be comparable between
|
|
compilers that support variadic macros and compilers that do not.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f1" class="footnote"><p><a href="#boost_contract.extras.no_macros__and_no_variadic_macros_.f1" class="para"><sup class="para">[81] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> The <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_MAX_ARGS.html" title="Macro BOOST_CONTRACT_MAX_ARGS">BOOST_CONTRACT_MAX_ARGS</a></code>
|
|
macro is named after <code class="computeroutput"><span class="identifier">BOOST_FUNCTION_MAX_ARGS</span></code>.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f2" class="footnote"><p><a href="#boost_contract.extras.no_macros__and_no_variadic_macros_.f2" class="para"><sup class="para">[82] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> These macros expand SFINAE-based
|
|
introspection templates that are too complex to be programmed manually
|
|
by users (that remains the case even if C++14 generic lambdas were to be
|
|
used here). On a related note, in theory using C++14 generic lambdas, the
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
macro could be re-implemented in a way that can be expanded at function
|
|
scope, instead of class scope (but there is not really a need to do that).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.extras.no_macros__and_no_variadic_macros_.f3" class="footnote"><p><a href="#boost_contract.extras.no_macros__and_no_variadic_macros_.f3" class="para"><sup class="para">[83] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> There is no need for the code
|
|
expanded by <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
to also use C++11 <code class="computeroutput"><span class="identifier">__func__</span></code>.
|
|
That is because <code class="computeroutput"><span class="identifier">__func__</span></code>
|
|
will always expand to the name of <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code> of the functor used to program the contract
|
|
assertions (e.g., of the lambda function) and it will not expand to the
|
|
name of the actual function specifying the contract.
|
|
</p></div>
|
|
</div>
|
|
</div>
|
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
|
<td align="left"></td>
|
|
<td align="right"><div class="copyright-footer">Copyright © 2008-2018 Lorenzo Caminiti<p>
|
|
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
|
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
|
</p>
|
|
</div></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="advanced.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="examples.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|