2518 lines
296 KiB
HTML
2518 lines
296 KiB
HTML
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<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"><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> 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, <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><code class="computeroutput"><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
behaves like <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>.
|
||
When <code class="computeroutput"><span class="identifier">T</span></code> is not copyable instead,
|
||
<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><code class="computeroutput"><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 to 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 (to avoid
|
||
run-time errors of dereferencing null pointers).
|
||
</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, for example in the contract assertions
|
||
using <code class="computeroutput"><span class="special">*</span><span class="identifier">old_x</span>
|
||
<span class="special">...</span></code> or <code class="computeroutput"><span class="identifier">old_x</span><span class="special">->...</span></code>). <a href="#ftn.boost_contract.extras.old_value_requirements__templates_.f1" class="footnote" name="boost_contract.extras.old_value_requirements__templates_.f1"><sup class="footnote">[69]</sup></a>
|
||
</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>).
|
||
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>
|
||
If programmers want to relax the copyable type requirement, they must do
|
||
so explicitly by using the <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>
|
||
type instead of using <code class="computeroutput"><span class="keyword">auto</span></code> declarations.
|
||
</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_.old_value_type_traits"></a></span><a class="link" href="extras.html#boost_contract.extras.old_value_requirements__templates_.old_value_type_traits">Old
|
||
Value Type Traits</a>
|
||
</h5>
|
||
<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.
|
||
</p>
|
||
<p>
|
||
By default, <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></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"><a class="link" href="../boost/contract/old_value_copy.html" title="Struct template old_value_copy">boost::contract::old_value_copy</a></code><code class="computeroutput"><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.
|
||
</p>
|
||
<p>
|
||
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 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>
|
||
<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 copyable or not. 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), or 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>
|
||
the following code will work also on non-C++11 compilers (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 just because of contract assertions and to simply
|
||
skip 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"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
||
on C++17 compilers, and <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>)
|
||
on non-C++17 compilers.
|
||
</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 guard this postcondition using C++17 <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></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 skip it otherwise. <a href="#ftn.boost_contract.extras.assertion_requirements__templates_.f0" class="footnote" name="boost_contract.extras.assertion_requirements__templates_.f0"><sup class="footnote">[70]</sup></a> For example:
|
||
</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">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>
|
||
More in general, <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
||
can be used to guard a mix of both old value copies and contract assertions
|
||
that introduce specific extra type requirements. For example, the following
|
||
<code class="computeroutput"><span class="identifier">swap</span></code> function can be called
|
||
on any type <code class="computeroutput"><span class="identifier">T</span></code> that is movable
|
||
but its old value copies and postcondition assertions are evaluated only
|
||
for types <code class="computeroutput"><span class="identifier">T</span></code> that are also
|
||
copyable and have an equality operator <code class="computeroutput"><span class="special">==</span></code>
|
||
(see <a href="../../../example/features/if_constexpr.cpp" target="_top"><code class="literal">if_constexpr.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">void</span> <span class="identifier">swap</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="identifier">T</span><span class="special">&</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="keyword">constexpr</span> <span class="keyword">bool</span> <span class="identifier">b</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">is_old_value_copyable</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</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</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> <span class="identifier">old_x</span><span class="special">,</span> <span class="identifier">old_y</span><span class="special">;</span>
|
||
<span class="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// Contract requires copyable T...</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">old_y</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">y</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">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="keyword">if</span> <span class="keyword">constexpr</span><span class="special">(</span><span class="identifier">b</span><span class="special">)</span> <span class="special">{</span> <span class="comment">// ... and T with `==`...</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_y</span><span class="special">);</span>
|
||
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">y</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="special">;</span>
|
||
|
||
<span class="identifier">T</span> <span class="identifier">t</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="comment">// ...but body only requires movable T.</span>
|
||
<span class="identifier">x</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span>
|
||
<span class="identifier">y</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">t</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<h5>
|
||
<a name="boost_contract.extras.assertion_requirements__templates_.h0"></a>
|
||
<span class="phrase"><a name="boost_contract.extras.assertion_requirements__templates_.no__code__phrase_role__keyword__if__phrase___phrase_role__keyword__constexpr__phrase___code___no_c__17_"></a></span><a class="link" href="extras.html#boost_contract.extras.assertion_requirements__templates_.no__code__phrase_role__keyword__if__phrase___phrase_role__keyword__constexpr__phrase___code___no_c__17_">No
|
||
<code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
||
(no C++17)</a>
|
||
</h5>
|
||
<p>
|
||
On non-C++17 compilers where <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code> is not available, it is possible
|
||
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>
|
||
to skip assertions based on type requirements (even if this code is less
|
||
readable and more verbose than using <code class="computeroutput"><span class="keyword">if</span>
|
||
<span class="keyword">constexpr</span></code>). For example (see <a href="../../../example/features/condition_if.cpp" target="_top"><code class="literal">condition_if.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">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>
|
||
<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"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></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"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></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>
|
||
(when used this way, 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"><a class="link" href="../boost/contract/condition_if.html" title="Function template condition_if">boost::contract::condition_if</a></code><code class="computeroutput"><span class="special"><</span><span class="identifier">Pred</span><span class="special">>(</span><span class="identifier">cond</span><span class="special">)</span></code> is logically equivalent to <code class="computeroutput"><a class="link" href="../boost/contract/call_if.html" title="Function template call_if">boost::contract::call_if</a></code><code class="computeroutput"><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">[71]</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 also 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 (including
|
||
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 functor template instantiations (not just 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>
|
||
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). 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>
|
||
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).
|
||
<a href="#ftn.boost_contract.extras.assertion_requirements__templates_.f2" class="footnote" name="boost_contract.extras.assertion_requirements__templates_.f2"><sup class="footnote">[72]</sup></a>
|
||
</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_idm45028039722128.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">[73]</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">[74]</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">auto</span> <span class="keyword">const</span> <span class="keyword">volatile</span><span class="special">*</span> <span class="identifier">cv</span> <span class="special">=</span> <span class="keyword">this</span><span class="special">;</span> <span class="identifier">cv</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, at a minimum 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 any other reason,
|
||
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_idm45028038882752.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="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">[75]</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_idm45028038882752.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 avoid the run-time overhead of checking contract
|
||
assertions and to maximize 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>
|
||
A C++ <code class="computeroutput"><span class="keyword">union</span></code> cannot have virtual
|
||
functions, base 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), instead <code class="computeroutput"><a class="link" href="../boost/contract/constructor_precondition.html" title="Class template constructor_precondition">boost::contract::constructor_precondition</a></code>
|
||
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 (as usual).</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 (as usual).</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="identifier">d_</span><span class="special">(</span><span class="number">0</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="special">{</span> <span class="keyword">int</span> <span class="identifier">y</span><span class="special">;</span> <span class="identifier">get</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span> <span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="identifier">x</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="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="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">[76]</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 the ones we have seen so far, they are always checked at run-time
|
||
and they cannot be disabled.
|
||
</li>
|
||
<li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028040814800.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 asserted conditions are always compiled
|
||
and therefore 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_idm45028067443360.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 therefore validated syntactically (so these assertions
|
||
can serve as formal comments to 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_idm45028040814800.html" title="Macro BOOST_CONTRACT_ASSERT_AUDIT">BOOST_CONTRACT_ASSERT_AUDIT</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028067443360.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_idm45028040814800.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_idm45028067443360.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 these assertion levels that are 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">EXPONENTIALLY_COMPLEX_ASSERTIONS</span>
|
||
<span class="comment">// Following will compile and also evaluate `cond`.</span>
|
||
<span class="preprocessor">#define</span> <span class="identifier">ASSERT_EXP</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">#else</span>
|
||
<span class="comment">// Following will compile but never actually evaluate `cond`.</span>
|
||
<span class="preprocessor">#define</span> <span class="identifier">ASSERT_EXP</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">#endif</span>
|
||
|
||
<span class="special">...</span>
|
||
|
||
<span class="identifier">ASSERT_EXP</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 groups
|
||
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_idm45028039660048.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_idm45028039653664.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_idm45028039634896.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_idm45028039627280.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_idm45028039619664.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 defining both <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028039634896.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_idm45028039627280.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 evaluate 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_idm45028039653664.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 overheads 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_idm45028039653664.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_idm45028039627280.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> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</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_idm45028039603040.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_idm45028039592176.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_idm45028039583904.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_idm45028039574704.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 compile-time
|
||
errors). Instead, these macros are automatically defined by this library
|
||
when programmers define <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028039660048.html" title="Macro BOOST_CONTRACT_NO_PRECONDITIONS">BOOST_CONTRACT_NO_PRECONDITIONS</a></code>,
|
||
<code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028039653664.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_idm45028039619664.html" title="Macro BOOST_CONTRACT_NO_INVARIANTS">BOOST_CONTRACT_NO_INVARIANTS</a></code>
|
||
(or <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028039634896.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_idm45028039627280.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 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>
|
||
that can also be used to completely disable compile-time and run-time overheads
|
||
introduced by contracts but without the burden of manually writing the <code class="computeroutput"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> statements. For example, the following
|
||
code shows how to use both the <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>
|
||
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 overheads 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_idm45028038671712.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>).
|
||
</p>
|
||
<p>
|
||
For constructors, destructors, and public functions the <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>
|
||
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 can be used as follow (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_idm45028038619104.html" title="Macro BOOST_CONTRACT_STATIC_INVARIANT">BOOST_CONTRACT_STATIC_INVARIANT</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028038632960.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 <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>
|
||
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 this 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 still 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 or 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 unless
|
||
<code class="computeroutput"><span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_CONTRACT_NO_</span><span class="special">...</span></code> statements are used).
|
||
</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
|
||
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 <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>
|
||
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 tool 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> (here named <code class="computeroutput"><span class="special">...</span><span class="identifier">_body</span></code>, but any other naming scheme could
|
||
be used) that are compiled in object files. Function definitions that remain
|
||
in header files instead will contain just contract code followed by calls
|
||
to the extra body functions. This technique allows to keep the contract code
|
||
in header files while separating the implementation code to source and object
|
||
files. However, this adds the overhead of manually programming an extra function
|
||
declaration for each 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">[77]</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, and protected 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_idm45028039653664.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_idm45028039627280.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). <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">[78]</sup></a>
|
||
</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_.f1" class="footnote" name="boost_contract.extras.no_lambda_functions__no_c__11_.f1"><sup class="footnote">[79]</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>).
|
||
</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, the header file (see <a href="../../../example/features/no_lambdas.hpp" target="_top"><code class="literal">no_lambdas.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">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>
|
||
And, the source file (see <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="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">
|
||
For constructors: 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">
|
||
For destructors: 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">[80]</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 (because of the large amount of boiler-plate code required
|
||
when C++11 lambdas are not used as also shown by the example above).
|
||
</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_idm45028038910320.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">[81]</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_idm45028038910320.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">[82]</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">[83]</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></code><code class="literal"><span class="emphasis"><em>cond</em></span></code><code class="computeroutput"><span class="special">)</span></code> simply 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">[84]</sup></a>
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">if</span><span class="special">(!(</span><code class="literal"><span class="emphasis"><em>cond</em></span></code><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><code class="literal"><span class="emphasis"><em>cond</em></span></code><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><code class="literal"><span class="emphasis"><em>cond</em></span></code><span class="special">)</span> <span class="keyword">throw</span> <code class="literal"><span class="emphasis"><em>exception-object</em></span></code><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>
|
||
As shown in <a class="link" href="extras.html#boost_contract.extras.assertion_levels" title="Assertion Levels">Assertion
|
||
Levels</a>, this library pre-defines <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028040814800.html" title="Macro BOOST_CONTRACT_ASSERT_AUDIT">BOOST_CONTRACT_ASSERT_AUDIT</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028067443360.html" title="Macro BOOST_CONTRACT_ASSERT_AXIOM">BOOST_CONTRACT_ASSERT_AXIOM</a></code>
|
||
assertion levels. These macros are not variadic macros and programmers should
|
||
be able to use them on all C++ compilers. In any case, 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><code class="literal"><span class="emphasis"><em>cond</em></span></code><span class="special">)</span> <span class="special">\</span>
|
||
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><code class="literal"><span class="emphasis"><em>cond</em></span></code><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><code class="literal"><span class="emphasis"><em>cond</em></span></code><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><code class="literal"><span class="emphasis"><em>cond</em></span></code><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><code class="literal"><span class="emphasis"><em>cond</em></span></code><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><code class="literal"><span class="emphasis"><em>cond</em></span></code><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_idm45028038942304.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 guarantee 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_idm45028038966352.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_idm45028038966352.html" title="Function make_old">boost::contract::make_old</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../boost/contract/copy_old_idm45028038942304.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_idm45028038966352.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 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 can 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 some kind
|
||
of <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.old_value_requirements__templates_.f1" class="footnote">
|
||
<p><a href="#boost_contract.extras.old_value_requirements__templates_.f1" class="para"><sup class="para">[69] </sup></a>
|
||
Technically, on C++17 it is possible to use <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
||
together with <code class="computeroutput"><span class="keyword">if</span> <span class="keyword">constexpr</span></code>
|
||
instead of 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>,
|
||
for example:
|
||
</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">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> <span class="identifier">old_x</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">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><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="keyword">if</span> <span class="keyword">constexpr</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">is_old_value_copyable</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">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>
|
||
However, the authors find this code less readable and more verbose than
|
||
its equivalent that uses <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>.
|
||
Guarding old value copies and related assertions with <code class="computeroutput"><span class="keyword">if</span>
|
||
<span class="keyword">constexpr</span></code> is useful instead when
|
||
the guard condition checks type requirements more complex than just <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>
|
||
(as shown later in this documentation).
|
||
</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">[70] </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 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 the
|
||
related type requirements (<a class="link" href="bibliography.html#N1962_anchor">[N1962]</a>
|
||
already allows of <code class="computeroutput"><span class="keyword">if</span></code> statements
|
||
in contracts 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 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">[71] </sup></a>
|
||
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>
|
||
is optimized and it 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">[72] </sup></a>
|
||
</p>
|
||
<p>
|
||
A part from its use within contracts, <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>
|
||
(<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). For example, the following implementation of <code class="computeroutput"><span class="identifier">myadvance</span></code> will compile since C++14
|
||
and it 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 (see
|
||
<a href="../../../example/features/call_if_cxx14.cpp" target="_top"><code class="literal">call_if_cxx14.cpp</code></a>):
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="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>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
Of course, since C++17 the implementation that uses <code class="computeroutput"><span class="keyword">if</span>
|
||
<span class="keyword">constexpr</span></code> is even more readable
|
||
and concise:
|
||
</p>
|
||
<pre class="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">i</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>
|
||
<p>
|
||
</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">[73] </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">[74] </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 a clear distinction and it 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">[75] </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_idm45028038882752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
||
from it for optimization reasons. However, calling <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45028038882752.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
|
||
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">[76] </sup></a>
|
||
The assertion levels predefined by this library are similar to the default,
|
||
audit, and axiom levels from <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">[77] </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 in function declarations instead
|
||
of definitions. That is because the C++11 standard does not allow lambdas
|
||
in function declarations to capture any variable (for the good reason that
|
||
it is not at all obvious how to correctly define the semantics of such
|
||
captures). For example, the following code is not valid C++ and it 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">[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_.f1" class="footnote"><p><a href="#boost_contract.extras.no_lambda_functions__no_c__11_.f1" class="para"><sup class="para">[79] </sup></a>
|
||
If C++ allowed lambda functions to capture variables by constant reference
|
||
(for example allowing a syntax like this <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>)
|
||
and 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_.f2" class="footnote"><p><a href="#boost_contract.extras.no_lambda_functions__no_c__11_.f2" class="para"><sup class="para">[80] </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">[81] </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">[82] </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">[83] </sup></a>
|
||
<span class="bold"><strong>Rationale:</strong></span> These macros expand to SFINAE-based
|
||
introspection template code 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">[84] </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 <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code> of the functor used to program the contract
|
||
assertions (e.g., the internal name the compiler assigns to lambda functions)
|
||
and it will not expand to the name of the actual function enclosing the
|
||
contract declaration.
|
||
</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-2019 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>
|