1895 lines
226 KiB
HTML
1895 lines
226 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
|
<title>Advanced</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="tutorial.html" title="Tutorial">
|
|
<link rel="next" href="extras.html" title="Extras">
|
|
</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="tutorial.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="extras.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.advanced"></a><a class="link" href="advanced.html" title="Advanced">Advanced</a>
|
|
</h2></div></div></div>
|
|
<div class="toc"><dl class="toc">
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.pure_virtual_public_functions">Pure
|
|
Virtual Public Functions</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.optional_return_values">Optional
|
|
Return Values</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.private_and_protected_functions">Private
|
|
and Protected Functions</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.friend_functions">Friend Functions</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.function_overloads">Function
|
|
Overloads</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__">Lambdas,
|
|
Loops, Code Blocks (and <code class="computeroutput"><span class="keyword">constexpr</span></code>)</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.implementation_checks">Implementation
|
|
Checks</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.old_value_copies_at_body">Old
|
|
Value Copies at Body</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.named_overrides">Named Overrides</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.access_specifiers">Access Specifiers</a></span></dt>
|
|
<dt><span class="section"><a href="advanced.html#boost_contract.advanced.throw_on_failures__and__noexcept__">Throw
|
|
on Failures (and <code class="computeroutput"><span class="keyword">noexcept</span></code>)</a></span></dt>
|
|
</dl></div>
|
|
<p>
|
|
This section is a guide to advanced usages of this library.
|
|
</p>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.pure_virtual_public_functions"></a><a class="link" href="advanced.html#boost_contract.advanced.pure_virtual_public_functions" title="Pure Virtual Public Functions">Pure
|
|
Virtual Public Functions</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
In C++, pure virtual functions are allowed to have a <a href="http://en.cppreference.com/w/cpp/language/abstract_class" target="_top">default
|
|
implementation</a> as long as such implementation is programmed out-of-line
|
|
so defined outside the class declaring the pure virtual function <code class="computeroutput"><span class="keyword">virtual</span> <span class="special">...</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span></code>.
|
|
</p>
|
|
<p>
|
|
Contracts for pure virtual public functions are programmed using the <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
function like for (non-pure) virtual public functions (all consideration
|
|
made in <a class="link" href="tutorial.html#boost_contract.tutorial.virtual_public_functions" title="Virtual Public Functions">Virtual
|
|
Public Functions</a> apply). However, contracts have to be programmed
|
|
out-of-line, in the default implementation of the pure virtual function.
|
|
For example (see <a href="../../../example/features/pure_virtual_public.cpp" target="_top"><code class="literal">pure_virtual_public.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">Iterator</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">range</span> <span class="special">{</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="comment">// Pure virtual function declaration (contract in definition below).</span>
|
|
<span class="keyword">virtual</span> <span class="identifier">Iterator</span> <span class="identifier">begin</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="number">0</span><span class="special">;</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"> <span class="comment">/* ... */</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Pure virtual function default implementation (out-of-line in C++).</span>
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Iterator</span><span class="special">></span>
|
|
<span class="identifier">Iterator</span> <span class="identifier">range</span><span class="special"><</span><span class="identifier">Iterator</span><span class="special">>::</span><span class="identifier">begin</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">Iterator</span> <span class="identifier">result</span><span class="special">;</span> <span class="comment">// As usual, virtual pass `result` right after `v`...</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="identifier">result</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">Iterator</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">result</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">empty</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">end</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="comment">// Pure function body (never executed by this library).</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
This library will never actually execute the pure virtual function body while
|
|
it is calling the pure virtual function default implementation to check contracts
|
|
for subcontracting. Therefore, programmers can safely <code class="computeroutput"><span class="identifier">assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span></code>
|
|
at the beginning of the body if they intend for that body to never be executed
|
|
(or they can program a working body in case they need to use pure virtual
|
|
function default implementations as usual in C++).
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.advanced.pure_virtual_public_functions.h0"></a>
|
|
<span class="phrase"><a name="boost_contract.advanced.pure_virtual_public_functions.subcontracting_preconditions_always_true_or_false"></a></span><a class="link" href="advanced.html#boost_contract.advanced.pure_virtual_public_functions.subcontracting_preconditions_always_true_or_false">Subcontracting
|
|
Preconditions Always True or False</a>
|
|
</h5>
|
|
<p>
|
|
As seen in <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>, preconditions of overriding public functions are
|
|
checked in <a class="link" href="contract_programming_overview.html#or_anchor"><code class="literal"><span class="emphasis"><em>OR</em></span></code></a>
|
|
with preconditions of overridden virtual public functions. Therefore, if
|
|
a virtual public function in a base class specifies no precondition then
|
|
preconditions specified by all its overriding functions in derived classes
|
|
will have no effect (because when checked in <a class="link" href="contract_programming_overview.html#or_anchor"><code class="literal"><span class="emphasis"><em>OR</em></span></code></a>
|
|
with the overridden function from the base class that has no preconditions,
|
|
they will always pass): <a href="#ftn.boost_contract.advanced.pure_virtual_public_functions.f0" class="footnote" name="boost_contract.advanced.pure_virtual_public_functions.f0"><sup class="footnote">[52]</sup></a>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">u</span> <span class="special">{</span> <span class="comment">// Some base class.</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">f</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">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="comment">// No preconditions, same as `ASSERT(true)`.</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>
|
|
</pre>
|
|
<p>
|
|
This correctly reflects the fact that the overridden function in the base
|
|
class can be called from any context (because it has no precondition) and
|
|
so must all its overriding functions in all derived classes in accordance
|
|
to the <a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle" target="_top">substitution
|
|
principle</a>. In other words, the code above has the effect as declaring
|
|
the virtual public function in the base class with a single precondition
|
|
<code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">true</span><span class="special">)</span></code> that
|
|
will always trivially pass:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">u</span> <span class="special">{</span> <span class="comment">// Some base class.</span>
|
|
<span class="keyword">public</span><span class="special">:</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">f</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">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="keyword">true</span><span class="special">);</span> <span class="comment">// Same as no preconditions.</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="special">};</span>
|
|
</pre>
|
|
<p>
|
|
On the flip side, programmers might sometimes consider to declare a pure
|
|
virtual public function in a base class with a single precondition <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span></code> that
|
|
will always fail. This indicates that the pure virtual public function can
|
|
never be called unless it is redefined by a derived class (which is already
|
|
the case with C++ pure virtual functions) and also that the base class designers
|
|
have intentionally left it up to derived classes to specify preconditions
|
|
for the pure virtual function in question. This technique might make sense
|
|
only for preconditions of pure virtual public functions (otherwise <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span></code> will
|
|
prevent calling virtual public functions in concrete bases). For example
|
|
(see <a href="../../../example/features/named_override.cpp" target="_top"><code class="literal">named_override.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">generic_unary_pack</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">_1</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="number">0</span><span class="special">;</span>
|
|
<span class="keyword">virtual</span> <span class="identifier">T</span> <span class="identifier">_1</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">const</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<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">generic_unary_pack</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">_1</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="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="keyword">false</span><span class="special">);</span> <span class="comment">// Defer preconditions to overrides.</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
That said, the need to declare such a precondition <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span></code>
|
|
that will always fail might be an indication that the base class interface
|
|
is not correctly designed. In general, the base class interface should still
|
|
contain all functions (eventually as pure virtual) that are necessary to
|
|
program its contracts.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.optional_return_values"></a><a class="link" href="advanced.html#boost_contract.advanced.optional_return_values" title="Optional Return Values">Optional
|
|
Return Values</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
It is possible to use <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code>
|
|
to handle return values when programmers cannot construct the result variable
|
|
at its point of declaration before the contract (e.g., because an appropriate
|
|
constructor for the return type is not available at that point, or just because
|
|
it would be too expensive to execute an extra initialization of the return
|
|
value at run-time). <a href="#ftn.boost_contract.advanced.optional_return_values.f0" class="footnote" name="boost_contract.advanced.optional_return_values.f0"><sup class="footnote">[53]</sup></a> For example (see <a href="../../../example/features/optional_result.cpp" target="_top"><code class="literal">optional_result.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">unsigned</span> <span class="identifier">Index</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
|
<span class="identifier">T</span><span class="special">&</span> <span class="identifier">get</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>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span> <span class="identifier">result</span><span class="special">;</span> <span class="comment">// Result not initialized 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">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">Index</span> <span class="special"><</span> <span class="identifier">vect</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">postcondition</span><span class="special">([&]</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">vect</span><span class="special">[</span><span class="identifier">Index</span><span class="special">]);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="comment">// Function body (executed after preconditions checked).</span>
|
|
<span class="keyword">return</span> <span class="special">*(</span><span class="identifier">result</span> <span class="special">=</span> <span class="identifier">vect</span><span class="special">[</span><span class="identifier">Index</span><span class="special">]);</span> <span class="comment">// ...result initialized here instead.</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
In this example the return type is a reference so it does not have default
|
|
constructor that can be used to initialize <code class="computeroutput"><span class="identifier">result</span></code>
|
|
when it is declared before the contract declaration. In addition, <code class="computeroutput"><span class="identifier">Index</span></code> needs to be validated to be smaller
|
|
than <code class="computeroutput"><span class="identifier">size</span><span class="special">()</span></code>
|
|
by the precondition before it can be used to retrieve the reference to assign
|
|
to <code class="computeroutput"><span class="identifier">result</span></code> so <code class="computeroutput"><span class="identifier">vect</span><span class="special">[</span><span class="identifier">Index</span><span class="special">]</span></code> cannot be used to initialize <code class="computeroutput"><span class="identifier">result</span></code> when it is declared before the contract
|
|
declaration. Therefore, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code>
|
|
is used to defer <code class="computeroutput"><span class="identifier">result</span></code> proper
|
|
initialization until the execution of the function body, after the contract
|
|
declaration, where <code class="computeroutput"><span class="identifier">Index</span></code>
|
|
has been validated by the precondition and <code class="computeroutput"><span class="identifier">vect</span><span class="special">[</span><span class="identifier">Index</span><span class="special">]</span></code> can be safely evaluated to initialize <code class="computeroutput"><span class="identifier">result</span></code>.
|
|
</p>
|
|
<p>
|
|
As seen in <a class="link" href="tutorial.html#boost_contract.tutorial.return_values" title="Return Values">Return Values</a>,
|
|
it is the responsibility of the programmers to ensure that <code class="computeroutput"><span class="identifier">result</span></code> is always set to the return value
|
|
(when the function exits without trowing an exception). This also ensures
|
|
that <code class="computeroutput"><span class="identifier">result</span></code> is always set
|
|
before the postconditions are checked so programmers can always dereference
|
|
<code class="computeroutput"><span class="identifier">result</span></code> in postconditions
|
|
to access the return value (using <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> and <code class="computeroutput"><span class="keyword">operator</span><span class="special">-></span></code> as usual with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code>,
|
|
and without having to explicitly check if <code class="computeroutput"><span class="identifier">result</span></code>
|
|
is an empty <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code> object or not). This can be done
|
|
ensuring that <span class="emphasis"><em>all</em></span> return statements in the function
|
|
are of the form:
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">return_type</span><span class="special">></span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="special">...</span>
|
|
<span class="keyword">return</span> <span class="special">*(</span><span class="identifier">result</span> <span class="special">=</span> <span class="identifier">return_expr</span><span class="special">);</span> <span class="comment">// Assign `result` at each return.</span>
|
|
</pre>
|
|
<h5>
|
|
<a name="boost_contract.advanced.optional_return_values.h0"></a>
|
|
<span class="phrase"><a name="boost_contract.advanced.optional_return_values.optional_results_in_virtual_public_functions"></a></span><a class="link" href="advanced.html#boost_contract.advanced.optional_return_values.optional_results_in_virtual_public_functions">Optional
|
|
Results in Virtual Public Functions</a>
|
|
</h5>
|
|
<p>
|
|
Similarly, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code> can be used to handle the return
|
|
value passed to contracts of virtual public functions (pure or not) and of
|
|
public function overrides. As seen in <a class="link" href="advanced.html#boost_contract.advanced.pure_virtual_public_functions" title="Pure Virtual Public Functions">Pure
|
|
Virtual Public Functions</a>, <a class="link" href="tutorial.html#boost_contract.tutorial.virtual_public_functions" title="Virtual Public Functions">Virtual
|
|
Public Functions</a>, and <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>, in these cases the return value <code class="computeroutput"><span class="identifier">result</span></code> must be passed as a parameter to
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
right after the parameter <code class="computeroutput"><span class="identifier">v</span></code>
|
|
of type <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>. Then the functor passed to <code class="computeroutput"><span class="special">.</span><span class="identifier">postcondition</span><span class="special">(...)</span></code> takes one single parameter of type
|
|
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span></code><code class="literal"><span class="emphasis"><em>return-type</em></span></code><code class="computeroutput">
|
|
<span class="keyword">const</span><span class="special">&></span>
|
|
<span class="keyword">const</span><span class="special">&</span></code>.
|
|
For example (see <a href="../../../example/features/optional_result_virtual.cpp" target="_top"><code class="literal">optional_result_virtual.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="identifier">T</span><span class="special">&</span> <span class="identifier">accessible</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">at</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">index</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">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="comment">// Pass `result` right after `v`...</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="identifier">result</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">index</span> <span class="special"><</span> <span class="identifier">size</span><span class="special">());</span>
|
|
<span class="special">})</span>
|
|
<span class="comment">// ...plus postconditions take `result` as a parameter (not capture).</span>
|
|
<span class="special">.</span><span class="identifier">postcondition</span><span class="special">([&]</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">result</span><span class="special">)</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="keyword">operator</span><span class="special">[](</span><span class="identifier">index</span><span class="special">));</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">);</span>
|
|
<span class="keyword">return</span> <span class="special">*</span><span class="identifier">result</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The inner <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code>
|
|
in the postcondition functor parameter type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><...</span> <span class="keyword">const</span><span class="special">&></span> <span class="special">...</span></code>
|
|
is mandatory (while the outer <code class="computeroutput"><span class="keyword">const</span><span class="special">&</span></code> in the postcondition functor parameter
|
|
type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><...></span>
|
|
<span class="keyword">const</span><span class="special">&</span></code>
|
|
is not). <a href="#ftn.boost_contract.advanced.optional_return_values.f1" class="footnote" name="boost_contract.advanced.optional_return_values.f1"><sup class="footnote">[54]</sup></a>
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.private_and_protected_functions"></a><a class="link" href="advanced.html#boost_contract.advanced.private_and_protected_functions" title="Private and Protected Functions">Private
|
|
and Protected Functions</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
Private and protected functions do not check class invariants (because they
|
|
are not part of the public class interface) and they do not subcontract (because
|
|
they are not accessible at the calling site where the <a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle" target="_top">substitution
|
|
principle</a> applies, see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.function_calls" title="Function Calls">Function
|
|
Calls</a>). However, programmers may still want to specify preconditions
|
|
and postconditions for private and protected functions when they want to
|
|
check correctness of their implementation and usage from within the class,
|
|
base classes, and friend classes or functions. When programmers decide to
|
|
specify contracts for private and protected functions, they shall use <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
(because, like for non-member functions, this does not check class invariants
|
|
and does not subcontract). For example (see <a href="../../../example/features/private_protected.cpp" target="_top"><code class="literal">private_protected.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">counter</span> <span class="special">{</span>
|
|
<span class="keyword">protected</span><span class="special">:</span> <span class="comment">// Protected functions use `function()` (like non-members).</span>
|
|
<span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">int</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">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">n</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">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">n</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">n_</span> <span class="special">=</span> <span class="identifier">n</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span> <span class="comment">// Private functions use `function()` (like non-members).</span>
|
|
<span class="keyword">void</span> <span class="identifier">dec</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_get</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">get</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">get</span><span class="special">()</span> <span class="special">+</span> <span class="number">1</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">min</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">get</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_get</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">set</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">-</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">n_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Considerations made in <a class="link" href="tutorial.html#boost_contract.tutorial.non_member_functions" title="Non-Member Functions">Non-Member
|
|
Functions</a> apply to private and protected functions as well. See <a class="link" href="tutorial.html#boost_contract.tutorial.constructors" title="Constructors">Constructors</a> and <a class="link" href="tutorial.html#boost_contract.tutorial.destructors" title="Destructors">Destructors</a> on how to
|
|
program contracts for private and protected constructors and destructors
|
|
instead.
|
|
</p>
|
|
<h5>
|
|
<a name="boost_contract.advanced.private_and_protected_functions.h0"></a>
|
|
<span class="phrase"><a name="boost_contract.advanced.private_and_protected_functions.virtual_private_and_protected_functions"></a></span><a class="link" href="advanced.html#boost_contract.advanced.private_and_protected_functions.virtual_private_and_protected_functions">Virtual
|
|
Private and Protected Functions</a>
|
|
</h5>
|
|
<p>
|
|
When private and protected functions are virtual they should still declare
|
|
the extra virtual parameter of type <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> with default value <code class="computeroutput"><span class="number">0</span></code>
|
|
(see <a class="link" href="tutorial.html#boost_contract.tutorial.virtual_public_functions" title="Virtual Public Functions">Virtual
|
|
Public Functions</a>) even if that parameter does not have to be passed
|
|
to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
takes no such an argument (so the extra virtual parameter will remain unused
|
|
and it does not need a name). <a href="#ftn.boost_contract.advanced.private_and_protected_functions.f0" class="footnote" name="boost_contract.advanced.private_and_protected_functions.f0"><sup class="footnote">[55]</sup></a> That is necessary otherwise the private and protected virtual
|
|
functions cannot be overridden by public functions in derived classes that
|
|
specify contracts (because the <code class="computeroutput"><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="special">=</span> <span class="number">0</span></code>
|
|
parameter has to be part of signatures for public function overrides). For
|
|
example (see <a href="../../../example/features/private_protected_virtual.cpp" target="_top"><code class="literal">private_protected_virtual.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">counter</span> <span class="special">{</span>
|
|
<span class="comment">// Virtual private and protected functions still declare extra</span>
|
|
<span class="comment">// `virtual_* = 0` parameter (otherwise they cannot be overridden), but...</span>
|
|
<span class="keyword">protected</span><span class="special">:</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">n</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="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">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="comment">// ...no `v`.</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">n</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">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">n</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">n_</span> <span class="special">=</span> <span class="identifier">n</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">dec</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="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_get</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">get</span><span class="special">());</span> <span class="comment">// ...no `v`.</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="comment">// ...no `v`.</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">get</span><span class="special">()</span> <span class="special">+</span> <span class="number">1</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">min</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">get</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_get</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">set</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">-</span> <span class="number">1</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">n_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
However, public functions in derived classes overriding private or protected
|
|
virtual functions from base classes shall not specify the extra <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code>
|
|
template parameter to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
because the overridden functions are private or protected and, not being
|
|
public, they do not participate to subcontracting (this library will generate
|
|
a compile-time error if <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code> is specified because there will be no
|
|
virtual public function to override from the base class). For example (see
|
|
<a href="../../../example/features/private_protected_virtual.cpp" target="_top"><code class="literal">private_protected_virtual.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">counter10</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">counter</span>
|
|
<span class="special">:</span> <span class="identifier">BASES</span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">public</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="comment">// Overriding from non-public members so no subcontracting, no override_...</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">n</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="comment">/* override */</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">n</span> <span class="special">%</span> <span class="number">10</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">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">n</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">counter</span><span class="special">::</span><span class="identifier">set</span><span class="special">(</span><span class="identifier">n</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">dec</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="comment">/* override */</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_get</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">get</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">get</span><span class="special">()</span> <span class="special">+</span> <span class="number">10</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">min</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">get</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_get</span> <span class="special">-</span> <span class="number">10</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">set</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">-</span> <span class="number">10</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Furthermore, using multiple inheritance it is possible to override functions
|
|
that are private or protected from one base but public from another base.
|
|
In this case, public function overrides in derived classes will specify the
|
|
extra <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code>
|
|
template parameter to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
(because the overridden functions are private or protected in one base and
|
|
those do not participate to subcontracting, but public in another base and
|
|
these participate to subcontracting instead). For example (see <a href="../../../example/features/private_protected_virtual_multi.cpp" target="_top"><code class="literal">private_protected_virtual_multi.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">countable</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">get</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">virtual</span> <span class="keyword">void</span> <span class="identifier">dec</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="number">0</span><span class="special">;</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">n</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="number">0</span><span class="special">;</span>
|
|
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">get</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">const</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">counter10</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">countable</span><span class="special">,</span> <span class="keyword">public</span> <span class="identifier">counter</span> <span class="comment">// Multiple inheritance.</span>
|
|
<span class="special">:</span> <span class="identifier">BASES</span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">public</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="comment">// Overriding from public members from `countable` so use `override_...`.</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">n</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="comment">/* override */</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">override_set</span><span class="special">>(</span><span class="identifier">v</span><span class="special">,</span> <span class="special">&</span><span class="identifier">counter10</span><span class="special">::</span><span class="identifier">set</span><span class="special">,</span> <span class="keyword">this</span><span class="special">,</span> <span class="identifier">n</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">n</span> <span class="special">%</span> <span class="number">10</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">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">n</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">counter</span><span class="special">::</span><span class="identifier">set</span><span class="special">(</span><span class="identifier">n</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">dec</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="comment">/* override */</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_get</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">get</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">override_dec</span><span class="special">>(</span><span class="identifier">v</span><span class="special">,</span> <span class="special">&</span><span class="identifier">counter10</span><span class="special">::</span><span class="identifier">dec</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">get</span><span class="special">()</span> <span class="special">+</span> <span class="number">10</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">min</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">get</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_get</span> <span class="special">-</span> <span class="number">10</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">set</span><span class="special">(</span><span class="identifier">get</span><span class="special">()</span> <span class="special">-</span> <span class="number">10</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="identifier">BOOST_CONTRACT_OVERRIDES</span><span class="special">(</span><span class="identifier">set</span><span class="special">,</span> <span class="identifier">dec</span><span class="special">)</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<div class="warning"><table border="0" summary="Warning">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/src/images/warning.png"></td>
|
|
<th align="left">Warning</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
Unfortunately, the code above does not compile on MSVC (at least up to
|
|
Visual Studio 2015) because MSVC incorrectly gives a compile-time error
|
|
when SFINAE fails due to private or protected access levels. Instead, GCC
|
|
and Clang correctly implement SFINAE failures due to private and protected
|
|
functions so the code above correctly complies on GCC and Clang. Therefore,
|
|
currently it is not possible to override a function that is public in one
|
|
base but private or protected in other base using this library on MSVC,
|
|
but that can correctly be done on GCC or Clang instead.
|
|
</p></td></tr>
|
|
</table></div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.friend_functions"></a><a class="link" href="advanced.html#boost_contract.advanced.friend_functions" title="Friend Functions">Friend Functions</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
Friend functions are not member functions so <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
can used to program contracts for them and all considerations made in <a class="link" href="tutorial.html#boost_contract.tutorial.non_member_functions" title="Non-Member Functions">Non-Member Functions</a>
|
|
apply. For example (see <a href="../../../example/features/friend.cpp" target="_top"><code class="literal">friend.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">buffer</span><span class="special">;</span>
|
|
|
|
<span class="keyword">class</span> <span class="identifier">byte</span> <span class="special">{</span>
|
|
<span class="keyword">friend</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">buffer</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">left</span><span class="special">,</span> <span class="identifier">byte</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">right</span><span class="special">);</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="keyword">char</span> <span class="identifier">value_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">buffer</span> <span class="special">{</span>
|
|
<span class="comment">// Friend functions are not member functions...</span>
|
|
<span class="keyword">friend</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">buffer</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">left</span><span class="special">,</span> <span class="identifier">byte</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">right</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// ...so check contracts via `function` (which won't 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">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">left</span><span class="special">.</span><span class="identifier">empty</span><span class="special">());</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(!</span><span class="identifier">right</span><span class="special">.</span><span class="identifier">empty</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">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">left</span><span class="special">.</span><span class="identifier">values_</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">();</span> <span class="special">*</span><span class="identifier">x</span> <span class="special">!=</span> <span class="char">'\0'</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">if</span><span class="special">(*</span><span class="identifier">x</span> <span class="special">!=</span> <span class="identifier">right</span><span class="special">.</span><span class="identifier">value_</span><span class="special">)</span> <span class="keyword">return</span> <span class="keyword">false</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>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">values_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
However, in some cases a friend function might take an object as parameter
|
|
and it can be logically considered an extension of that object's public interface
|
|
(essentially at the same level as the object's public functions). In these
|
|
cases, programmers might chose to program the friend function contracts using
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
(instead of <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>)
|
|
so to also check the class invariants of the object passed as parameter (and
|
|
not just pre- and postconditions). For example (see <a href="../../../example/features/friend_invariant.cpp" target="_top"><code class="literal">friend_invariant.cpp</code></a>):
|
|
<a href="#ftn.boost_contract.advanced.friend_functions.f0" class="footnote" name="boost_contract.advanced.friend_functions.f0"><sup class="footnote">[56]</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="keyword">class</span> <span class="identifier">positive</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">value</span><span class="special">()</span> <span class="special">></span> <span class="number">0</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Can be considered an extension of enclosing class' public interface...</span>
|
|
<span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">positive</span><span class="special">&</span> <span class="identifier">object</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="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_object_value</span> <span class="special">=</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">object</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_value</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span>
|
|
<span class="comment">// ...so it can be made to check invariants via `public_function`.</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">object</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">value</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">postcondition</span><span class="special">([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">object</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">old_value</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">value</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_object_value</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">T</span> <span class="identifier">saved</span> <span class="special">=</span> <span class="identifier">object</span><span class="special">.</span><span class="identifier">value_</span><span class="special">;</span>
|
|
<span class="identifier">object</span><span class="special">.</span><span class="identifier">value_</span> <span class="special">=</span> <span class="identifier">value</span><span class="special">;</span>
|
|
<span class="identifier">value</span> <span class="special">=</span> <span class="identifier">saved</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">T</span> <span class="identifier">value_</span><span class="special">;</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
This technique can also be extended to friend functions that take multiple
|
|
objects as parameters and can be logically considered extensions to the public
|
|
interfaces of each of these objects. For example:
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">// Can be considered an extension of multiple objects' public interfaces.</span>
|
|
<span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">class1</span><span class="special">&</span> <span class="identifier">object1</span><span class="special">,</span> <span class="identifier">class2</span><span class="special">*</span> <span class="identifier">object2</span><span class="special">,</span> <span class="identifier">type3</span><span class="special">&</span> <span class="identifier">value3</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// Check 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">pre</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">object2</span> <span class="special">!=</span> <span class="keyword">nullptr</span><span class="special">);</span>
|
|
<span class="special">...</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
<span class="comment">// Check class invariants for each object (programmers chose the order).</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">inv1</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">object1</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">inv2</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">object2</span><span class="special">);</span>
|
|
<span class="comment">// Check postconditions and exception guarantees.</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">post_except</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="identifier">except</span><span class="special">(...)</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="special">...</span> <span class="comment">// Function body.</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
Changing the order of the <code class="computeroutput"><a class="link" href="../boost/contract/check.html" title="Class check">boost::contract::check</a></code>
|
|
declarations above, programmers can chose the order for checking class invariants
|
|
among the different objects passed to the friend function and also whether
|
|
to check these invariants before or after preconditions, postconditions,
|
|
and exception guarantees of the friend function (see <a class="link" href="tutorial.html#boost_contract.tutorial.non_member_functions" title="Non-Member Functions">Non-Member
|
|
Functions</a> and <a class="link" href="tutorial.html#boost_contract.tutorial.public_functions" title="Public Functions">Public
|
|
Functions</a> for information on how the RAII objects returned by <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
check contract conditions). The example above is programmed to check <code class="computeroutput"><span class="identifier">class1</span></code> invariants before <code class="computeroutput"><span class="identifier">class2</span></code> invariants (but the order could
|
|
have been inverted if programmers so chose).
|
|
</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>
|
|
In the example above, preconditions are intentionally programmed to be
|
|
checked before class invariants so the objects passed to the friend function
|
|
can be validated by the preconditions before they are passed as pointers
|
|
to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
(e.g., check <code class="computeroutput"><span class="identifier">object2</span></code> is
|
|
not null). (Within member functions instead, the object pointer <code class="computeroutput"><span class="keyword">this</span></code> is always well-formed, its validation
|
|
is never needed, and <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
checks class invariants before checking preconditions so programming preconditions
|
|
can be simplified assuming the class invariants are satisfied already,
|
|
see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.public_function_calls" title="Public Function Calls">Public
|
|
Function Calls</a>.)
|
|
</p></td></tr>
|
|
</table></div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.function_overloads"></a><a class="link" href="advanced.html#boost_contract.advanced.function_overloads" title="Function Overloads">Function
|
|
Overloads</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
No special attention is required when using this library with overloaded
|
|
functions or constructors. The only exception is for the function pointer
|
|
passed to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
from public function overrides (see <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>). When the name of public function override are
|
|
also overloaded, the related function pointer cannot be automatically deduced
|
|
by the compiler so programmers have to use <code class="computeroutput"><span class="keyword">static_cast</span></code>
|
|
to resolve ambiguities (as usual with pointers to overloaded functions in
|
|
C++). <a href="#ftn.boost_contract.advanced.function_overloads.f0" class="footnote" name="boost_contract.advanced.function_overloads.f0"><sup class="footnote">[57]</sup></a> For example, note how <code class="computeroutput"><span class="keyword">static_cast</span></code>
|
|
is used in the following calls to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
(see <a href="../../../example/features/overload.cpp" target="_top"><code class="literal">overload.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">string_lines</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">lines</span>
|
|
<span class="special">:</span> <span class="identifier">BASES</span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">public</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_OVERRIDES</span><span class="special">(</span><span class="identifier">str</span><span class="special">)</span> <span class="comment">// Invoked only once for all `str` overloads.</span>
|
|
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">str</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">const</span> <span class="comment">/* override */</span> <span class="special">{</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</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">public_function</span><span class="special"><</span>
|
|
<span class="identifier">override_str</span><span class="special">>(</span>
|
|
<span class="identifier">v</span><span class="special">,</span> <span class="identifier">result</span><span class="special">,</span>
|
|
<span class="comment">// `static_cast` resolves overloaded function pointer ambiguities.</span>
|
|
<span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">(</span><span class="identifier">string_lines</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="keyword">const</span><span class="special">>(&</span><span class="identifier">string_lines</span><span class="special">::</span><span class="identifier">str</span><span class="special">),</span>
|
|
<span class="keyword">this</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">str_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Overload on (absence of) `const` qualifier.</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&</span> <span class="identifier">str</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="comment">/* override */</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">override_str</span><span class="special">>(</span>
|
|
<span class="identifier">v</span><span class="special">,</span> <span class="identifier">str_</span><span class="special">,</span>
|
|
<span class="comment">// `static_cast` resolves overloaded function pointer ambiguities.</span>
|
|
<span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&</span> <span class="special">(</span><span class="identifier">string_lines</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">string_lines</span><span class="special">::</span><span class="identifier">str</span><span class="special">),</span>
|
|
<span class="keyword">this</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="keyword">return</span> <span class="identifier">str_</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="identifier">BOOST_CONTRACT_OVERRIDES</span><span class="special">(</span><span class="identifier">put</span><span class="special">)</span> <span class="comment">// Invoked only once for all `put` overloads.</span>
|
|
|
|
<span class="keyword">void</span> <span class="identifier">put</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</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="special">)</span> <span class="comment">/* override */</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">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span> <span class="identifier">old_str</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">str</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">override_put</span><span class="special">>(</span>
|
|
<span class="identifier">v</span><span class="special">,</span>
|
|
<span class="comment">// `static_cast` resolves overloaded function pointer ambiguities.</span>
|
|
<span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">void</span> <span class="special">(</span><span class="identifier">string_lines</span><span class="special">::*)(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</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">virtual_</span><span class="special">*)>(&</span><span class="identifier">string_lines</span><span class="special">::</span><span class="identifier">put</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="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">str</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_str</span> <span class="special">+</span> <span class="identifier">x</span> <span class="special">+</span> <span class="char">'\n'</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">str_</span> <span class="special">=</span> <span class="identifier">str_</span> <span class="special">+</span> <span class="identifier">x</span> <span class="special">+</span> <span class="char">'\n'</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Overload on argument type.</span>
|
|
<span class="keyword">void</span> <span class="identifier">put</span><span class="special">(</span><span class="keyword">char</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="special">)</span> <span class="comment">/* override */</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">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span> <span class="identifier">old_str</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">str</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">override_put</span><span class="special">>(</span>
|
|
<span class="identifier">v</span><span class="special">,</span>
|
|
<span class="comment">// `static_cast` resolves overloaded function pointer ambiguities.</span>
|
|
<span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">void</span> <span class="special">(</span><span class="identifier">string_lines</span><span class="special">::*)(</span><span class="keyword">char</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">string_lines</span><span class="special">::</span><span class="identifier">put</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="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">str</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_str</span> <span class="special">+</span> <span class="identifier">x</span> <span class="special">+</span> <span class="char">'\n'</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">str_</span> <span class="special">=</span> <span class="identifier">str_</span> <span class="special">+</span> <span class="identifier">x</span> <span class="special">+</span> <span class="char">'\n'</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="comment">// Overload on argument type and arity (also with default parameter).</span>
|
|
<span class="keyword">void</span> <span class="identifier">put</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">bool</span> <span class="identifier">tab</span> <span class="special">=</span> <span class="keyword">false</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="comment">/* override */</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">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">></span> <span class="identifier">old_str</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">str</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">override_put</span><span class="special">>(</span>
|
|
<span class="identifier">v</span><span class="special">,</span>
|
|
<span class="comment">// `static_cast` resolves overloaded function pointer ambiguities.</span>
|
|
<span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">void</span> <span class="special">(</span><span class="identifier">string_lines</span><span class="special">::*)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">bool</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">string_lines</span><span class="special">::</span><span class="identifier">put</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">tab</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">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">s</span><span class="special">;</span>
|
|
<span class="identifier">s</span> <span class="special"><<</span> <span class="identifier">x</span><span class="special">;</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span>
|
|
<span class="identifier">str</span><span class="special">()</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_str</span> <span class="special">+</span> <span class="special">(</span><span class="identifier">tab</span> <span class="special">?</span> <span class="string">"\t"</span> <span class="special">:</span> <span class="string">""</span><span class="special">)</span> <span class="special">+</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">str</span><span class="special">()</span> <span class="special">+</span> <span class="char">'\n'</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">s</span><span class="special">;</span>
|
|
<span class="identifier">s</span> <span class="special"><<</span> <span class="identifier">str_</span> <span class="special"><<</span> <span class="special">(</span><span class="identifier">tab</span> <span class="special">?</span> <span class="string">"\t"</span> <span class="special">:</span> <span class="string">""</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">x</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">;</span>
|
|
<span class="identifier">str_</span> <span class="special">=</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">str</span><span class="special">();</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="keyword">private</span><span class="special">:</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">str_</span><span class="special">;</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Overloaded functions have the same function name so the same <code class="literal">override_<span class="emphasis"><em>function-name</em></span></code>
|
|
type can be reused as template parameter for all <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
calls in a given class. Therefore, <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
only needs to be invoked once for a function name in a given class, even
|
|
when that function name is overloaded.
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__"></a><a class="link" href="advanced.html#boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__" title="Lambdas, Loops, Code Blocks (and constexpr)">Lambdas,
|
|
Loops, Code Blocks (and <code class="computeroutput"><span class="keyword">constexpr</span></code>)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
While contracts are usually most useful to program specifications of functions
|
|
and class interfaces, this library also allows to check contract conditions
|
|
for implementation code (lambda functions, loops, code blocks, etc.).
|
|
</p>
|
|
<p>
|
|
Lambda functions are not member functions, they are not part of class public
|
|
interfaces so they do not check class invariants and they do not subcontract.
|
|
They can use <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
to specify preconditions, postconditions, and exception guarantees (considerations
|
|
made in <a class="link" href="tutorial.html#boost_contract.tutorial.non_member_functions" title="Non-Member Functions">Non-Member
|
|
Functions</a> apply). For example (see <a href="../../../example/features/lambda.cpp" target="_top"><code class="literal">lambda.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">total</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">v</span><span class="special">.</span><span class="identifier">cbegin</span><span class="special">(),</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">cend</span><span class="special">(),</span>
|
|
<span class="comment">// Contract for a lambda function.</span>
|
|
<span class="special">[&</span><span class="identifier">total</span><span class="special">]</span> <span class="special">(</span><span class="keyword">int</span> <span class="keyword">const</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">old_ptr</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">old_total</span> <span class="special">=</span>
|
|
<span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">total</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">total</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="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">total</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_total</span> <span class="special">+</span> <span class="identifier">x</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">total</span> <span class="special">+=</span> <span class="identifier">x</span><span class="special">;</span> <span class="comment">// Lambda function body.</span>
|
|
<span class="special">}</span>
|
|
<span class="special">);</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Similarly, <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
can be used to program preconditions, postconditions, and exception guarantees
|
|
for loops. For example, for a for-loop but same for while- and all other
|
|
loops (see <a href="../../../example/features/loop.cpp" target="_top"><code class="literal">loop.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">total</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="comment">// Contract for a for-loop (same for while- and all other loops).</span>
|
|
<span class="keyword">for</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="keyword">int</span><span class="special">>::</span><span class="identifier">const_iterator</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">begin</span><span class="special">();</span> <span class="identifier">i</span> <span class="special">!=</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">end</span><span class="special">();</span> <span class="special">++</span><span class="identifier">i</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_total</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">total</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">total</span> <span class="special">+</span> <span class="special">*</span><span class="identifier">i</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="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">total</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_total</span> <span class="special">+</span> <span class="special">*</span><span class="identifier">i</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">total</span> <span class="special">+=</span> <span class="special">*</span><span class="identifier">i</span><span class="special">;</span> <span class="comment">// For-loop body.</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
More in general, <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
can be used to program preconditions, postconditions, and exception guarantees
|
|
of any block of code in a given function. For example (see <a href="../../../example/features/code_block.cpp" target="_top"><code class="literal">code_block.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">/* ... */</span>
|
|
|
|
<span class="comment">// Contract for a code block.</span>
|
|
<span class="special">{</span> <span class="comment">// Code block entry (check preconditions).</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_total</span> <span class="special">=</span> <span class="identifier">BOOST_CONTRACT_OLDOF</span><span class="special">(</span><span class="identifier">total</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">v</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="number">3</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">total</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">old_total</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">v</span><span class="special">[</span><span class="number">1</span><span class="special">]</span> <span class="special">+</span> <span class="identifier">v</span><span class="special">[</span><span class="number">2</span><span class="special">]);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">total</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">v</span><span class="special">[</span><span class="number">1</span><span class="special">]</span> <span class="special">+</span> <span class="identifier">v</span><span class="special">[</span><span class="number">2</span><span class="special">];</span> <span class="comment">// Code block body.</span>
|
|
<span class="special">}</span> <span class="comment">// Code block exit (check postconditions and exceptions guarantees).</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Finally, at the moment this library does not support contracts for functions
|
|
and classes declared <code class="computeroutput"><span class="keyword">constexpr</span></code>.
|
|
<a href="#ftn.boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__.f0" class="footnote" name="boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__.f0"><sup class="footnote">[58]</sup></a>
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.implementation_checks"></a><a class="link" href="advanced.html#boost_contract.advanced.implementation_checks" title="Implementation Checks">Implementation
|
|
Checks</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
This library provides a mechanism to check assertions within implementation
|
|
code a part from preconditions, postconditions, exceptions guarantees, and
|
|
class invariants. Implementation checks are programmed using a nullary functor
|
|
that is directly assigned to a <code class="computeroutput"><a class="link" href="../boost/contract/check.html" title="Class check">boost::contract::check</a></code>
|
|
object declaration right at the place within the code where the checks need
|
|
to be performed (without calling <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>,
|
|
etc. in this case). For example (see <a href="../../../example/features/check.cpp" target="_top"><code class="literal">check.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="comment">// Implementation checks (via nullary functor).</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="special">[&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">gcd</span><span class="special">(</span><span class="number">12</span><span class="special">,</span> <span class="number">28</span><span class="special">)</span> <span class="special">==</span> <span class="number">4</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">gcd</span><span class="special">(</span><span class="number">4</span><span class="special">,</span> <span class="number">14</span><span class="special">)</span> <span class="special">==</span> <span class="number">2</span><span class="special">);</span>
|
|
<span class="special">};</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The implementation check functor should capture all the variables that it
|
|
needs to assert the implementation checks. These variables can be captured
|
|
by value when the overhead of copying such variables is acceptable. In any
|
|
case, implementation checks should not modify the value of the captured variables,
|
|
even when those are captured by reference (see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>).
|
|
</p>
|
|
<p>
|
|
Any code can be programmed in the implementation check functor, but it is
|
|
recommended to keep this code simple using mainly assertions and if-statements
|
|
(to avoid programming complex checks that might be buggy and also slow to
|
|
check at run-time). It is also recommended to use <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
to program the assertions because that enables this library to print informative
|
|
error messages when the asserted conditions are evaluated to be false (this
|
|
is not a variadic macro, 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>):
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">bool_cond</span><span class="special">)</span>
|
|
<span class="comment">// Or, if `bool_cond` contains commas `,` not already within parenthesis `()`...</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">((</span><span class="identifier">bool_cond</span><span class="special">))</span> <span class="comment">// ...use extra parenthesis (not a variadic macro).</span>
|
|
</pre>
|
|
<p>
|
|
This library will automatically call the failure handler <code class="computeroutput"><a class="link" href="../boost/contract/check_failure.html" title="Function check_failure">boost::contract::check_failure</a></code>
|
|
if any of the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
conditions are false and, more in general, if calling the implementation
|
|
check functor throws any exception. By default, this failure handler prints
|
|
an error message to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span></code> and terminates the program calling
|
|
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span></code> (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> to change the failure handler to throw exceptions, exit
|
|
the program with an error code, etc.).
|
|
</p>
|
|
<p>
|
|
Similarly to the C-style <code class="computeroutput"><span class="identifier">assert</span></code>
|
|
macro that is disable when <code class="computeroutput"><span class="identifier">NDEBUG</span></code>
|
|
is defined, implementation checks are disabled when <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>
|
|
is defined. That will skip all implementation checks at run-time but it will
|
|
not eliminate some of the overhead of executing and compiling the related
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/check.html" title="Class check">boost::contract::check</a></code>
|
|
declarations. Alternatively, this library provides the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_CHECK.html" title="Macro BOOST_CONTRACT_CHECK">BOOST_CONTRACT_CHECK</a></code>
|
|
macro that allows to completely remove run- and compile-time overhead of
|
|
implementation checks when <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>
|
|
is defined (this is not a variadic macro):
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">(</span><span class="identifier">bool_cond</span><span class="special">)</span>
|
|
<span class="comment">// Or, if `bool_cond` contains commas `,` not already within parenthesis `()`...</span>
|
|
<span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">((</span><span class="identifier">bool_cond</span><span class="special">))</span> <span class="comment">// ...use extra parenthesis (not a variadic macro).</span>
|
|
</pre>
|
|
<p>
|
|
For example (see <a href="../../../example/features/check_macro.cpp" target="_top"><code class="literal">check_macro.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
|
|
<span class="comment">// Implementation checks (via macro, disable run-/compile-time overhead).</span>
|
|
<span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">(</span><span class="identifier">gcd</span><span class="special">(</span><span class="number">12</span><span class="special">,</span> <span class="number">28</span><span class="special">)</span> <span class="special">==</span> <span class="number">4</span><span class="special">);</span>
|
|
<span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">(</span><span class="identifier">gcd</span><span class="special">(</span><span class="number">4</span><span class="special">,</span> <span class="number">14</span><span class="special">)</span> <span class="special">==</span> <span class="number">2</span><span class="special">);</span>
|
|
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_CHECK.html" title="Macro BOOST_CONTRACT_CHECK">BOOST_CONTRACT_CHECK</a></code>
|
|
macro is similar to the C-style assert macro as it accepts a boolean condition
|
|
(instead of a nullary functor like <code class="computeroutput"><a class="link" href="../boost/contract/check.html" title="Class check">boost::contract::check</a></code>
|
|
does). <a href="#ftn.boost_contract.advanced.implementation_checks.f0" class="footnote" name="boost_contract.advanced.implementation_checks.f0"><sup class="footnote">[59]</sup></a> Using <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_CHECK.html" title="Macro BOOST_CONTRACT_CHECK">BOOST_CONTRACT_CHECK</a></code>
|
|
is essentially equivalent to using the C-style <code class="computeroutput"><span class="identifier">assert</span></code>
|
|
macro a part from the following:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Implementation checks are disabled defining <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_NO_CHECKS.html" title="Macro BOOST_CONTRACT_NO_CHECKS">BOOST_CONTRACT_NO_CHECKS</a></code>
|
|
(instead of <code class="computeroutput"><span class="identifier">NDEBUG</span></code> for
|
|
disabling <code class="computeroutput"><span class="identifier">assert</span></code>).
|
|
</li>
|
|
<li class="listitem">
|
|
If the asserted boolean condition is either false or it throws an exception
|
|
then this library will call <code class="computeroutput"><a class="link" href="../boost/contract/check_failure.html" title="Function check_failure">boost::contract::check_failure</a></code>
|
|
(instead <code class="computeroutput"><span class="identifier">assert</span></code> calls
|
|
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">abort</span></code> if the asserted condition is
|
|
false and unwinds the stack if evaluating the condition throws an exception).
|
|
</li>
|
|
<li class="listitem">
|
|
Implementation checks are automatically disabled when other contract
|
|
conditions specified using this library are already being checked (to
|
|
avoid infinite recursion, see <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123870534752.html" title="Macro BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION">BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION</a></code>).
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
(See <a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
|
Contract Checking</a> and <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 macros to completely remove run- and compile-time
|
|
overhead also for preconditions, postconditions, exception guarantees, and
|
|
class invariants.)
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.old_value_copies_at_body"></a><a class="link" href="advanced.html#boost_contract.advanced.old_value_copies_at_body" title="Old Value Copies at Body">Old
|
|
Value Copies at Body</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
In the examples seen so far, old value variables 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>
|
|
are initialized to a copy of 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>
|
|
as soon as they are declared. This is correctly happens before the function
|
|
body is executed but also before the contract is declared, therefore even
|
|
before class invariants (for public functions) and preconditions are checked
|
|
at function entry. This might work well in most practical cases, however
|
|
technically old values should be copied before executing the function body
|
|
but <span class="emphasis"><em>after</em></span> checking entry class invariants and preconditions
|
|
(see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.assertions" title="Assertions">Assertions</a>).
|
|
Specifically, there could be cases in which it makes sense to evaluate the
|
|
expressions passed to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
only under the assumption that assertions programmed in class invariants
|
|
and preconditions are true.
|
|
</p>
|
|
<p>
|
|
This library allows to construct <code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code>
|
|
variables using their default constructor (equivalent to a null pointer)
|
|
and then to later assign them to a copy of 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> in a nullary
|
|
functor <code class="literal"><span class="emphasis"><em>d</em></span></code><code class="computeroutput"><span class="special">()</span></code>
|
|
passed to <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>d</em></span></code><code class="computeroutput"><span class="special">)</span></code>. The functor <code class="literal"><span class="emphasis"><em>d</em></span></code><code class="computeroutput"><span class="special">()</span></code> is called by this library before the function
|
|
body is executed but only after class invariants and preconditions are checked.
|
|
Old value assignments via <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>
|
|
must appear after preconditions but before postconditions and exception guarantees
|
|
wen these are all present (see <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>,
|
|
and <a class="link" href="tutorial.html#boost_contract.tutorial.exception_guarantees" title="Exception Guarantees">Exception
|
|
Guarantees</a>). <a href="#ftn.boost_contract.advanced.old_value_copies_at_body.f0" class="footnote" name="boost_contract.advanced.old_value_copies_at_body.f0"><sup class="footnote">[60]</sup></a>
|
|
</p>
|
|
<p>
|
|
For example, the following old value expression <code class="computeroutput"><span class="identifier">s</span><span class="special">[</span><span class="identifier">index</span><span class="special">]</span></code> passed to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>
|
|
is valid only after the precondition has checked that <code class="computeroutput"><span class="identifier">index</span></code>
|
|
is within valid range <code class="computeroutput"><span class="identifier">index</span> <span class="special"><</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span></code>.
|
|
Therefore, <code class="computeroutput"><span class="identifier">old_y</span></code> is first
|
|
declared using its default constructor (i.e., initialized to a null pointer)
|
|
and later assigned to a copy of <code class="computeroutput"><span class="identifier">s</span><span class="special">[</span><span class="identifier">index</span><span class="special">]</span></code> in <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>
|
|
after the precondition has checked <code class="computeroutput"><span class="identifier">index</span></code>
|
|
(see <a href="../../../example/features/old.cpp" target="_top"><code class="literal">old.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">char</span> <span class="identifier">replace</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&</span> <span class="identifier">s</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">index</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">char</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">char</span><span class="special">></span> <span class="identifier">old_y</span><span class="special">;</span> <span class="comment">// Null, old value copied later...</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">index</span> <span class="special"><</span> <span class="identifier">s</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</span><span class="special">([&]</span> <span class="special">{</span> <span class="comment">// ...after preconditions (and invariants) checked.</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">s</span><span class="special">[</span><span class="identifier">index</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">s</span><span class="special">[</span><span class="identifier">index</span><span class="special">]</span> <span class="special">==</span> <span class="identifier">x</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_y</span><span class="special">);</span>
|
|
<span class="special">})</span>
|
|
<span class="special">;</span>
|
|
|
|
<span class="identifier">result</span> <span class="special">=</span> <span class="identifier">s</span><span class="special">[</span><span class="identifier">index</span><span class="special">];</span>
|
|
<span class="identifier">s</span><span class="special">[</span><span class="identifier">index</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
|
|
<span class="keyword">return</span> <span class="identifier">result</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
The functor passed to <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code> should capture all variables it needs
|
|
to evaluate to copy the old value expressions passed to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>.
|
|
In general, these variables should be captured by reference and not by value
|
|
(because old values need to make copies of the values the captured variables
|
|
will have just before executing the function body, and not copy the values
|
|
these variables had when the functor passed to <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>
|
|
was first declared). In any case, the functor passed to <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>
|
|
should modify only old values and not the values of other captured variables
|
|
(see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>).
|
|
</p>
|
|
<p>
|
|
This library will automatically call the failure handler <code class="computeroutput"><a class="link" href="../boost/contract/old_failure.html" title="Function old_failure">boost::contract::old_failure</a></code>
|
|
if calling the functor specified via <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>
|
|
throws an exception (by default, this handler prints an error message to
|
|
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span></code> and terminates the program calling
|
|
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span></code>, but 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> to throw exceptions, exit the program with an error code,
|
|
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>
|
|
If old value pointers are initialized at the point of their construction
|
|
instead of using <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code> then an exception thrown by the old
|
|
value expression passed to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code>,
|
|
or more in general any exception thrown by the old value pointer initialization,
|
|
will result in that exception being thrown up the stack by the enclosing
|
|
function. This is arguably less correct than calling <code class="computeroutput"><a class="link" href="../boost/contract/old_failure.html" title="Function old_failure">boost::contract::old_failure</a></code>
|
|
because an exception thrown by an old value copy causes the program to
|
|
fail to check its postconditions and exception guarantees but should not
|
|
automatically causes the enclosing function to thrown an exception (this
|
|
might not be a significant difference in practice, but it could be an additional
|
|
reason to use <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code> instead of assigning old values when
|
|
they are declared before the contract). <a href="#ftn.boost_contract.advanced.old_value_copies_at_body.f1" class="footnote" name="boost_contract.advanced.old_value_copies_at_body.f1"><sup class="footnote">[61]</sup></a>
|
|
</p></td></tr>
|
|
</table></div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.named_overrides"></a><a class="link" href="advanced.html#boost_contract.advanced.named_overrides" title="Named Overrides">Named Overrides</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
As seen in <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>, the <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
macro has to be used to declare a type <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code> that is passed to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
for public function overrides. The function names passed to <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_CONTRACT_OVERRIDES.html" title="Macro BOOST_CONTRACT_OVERRIDES">BOOST_CONTRACT_OVERRIDES</a></code>)
|
|
should never start with an underscore to avoid generating names containing
|
|
double underscores <code class="computeroutput"><span class="identifier">override__</span><span class="special">...</span></code> (which are reserved by the C++ standard).
|
|
There is a separate macro <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>
|
|
that can be used to explicitly specify the name of the type being declared:
|
|
<a href="#ftn.boost_contract.advanced.named_overrides.f0" class="footnote" name="boost_contract.advanced.named_overrides.f0"><sup class="footnote">[62]</sup></a>
|
|
</p>
|
|
<pre class="programlisting"><span class="identifier">BOOST_CONTRACT_OVERRIDE</span><span class="special">(</span><span class="identifier">func_name</span><span class="special">)</span> <span class="comment">// Generate `override_...`.</span>
|
|
<span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDE</span><span class="special">(</span><span class="identifier">type_name</span><span class="special">,</span> <span class="identifier">func_name</span><span class="special">)</span> <span class="comment">// Generate `type_name`.</span>
|
|
</pre>
|
|
<p>
|
|
For example, the following public function override is named <code class="computeroutput"><span class="identifier">_1</span></code> so <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_OVERRIDE</span><span class="special">(</span><span class="identifier">_1</span><span class="special">)</span></code>
|
|
would declare a type named <code class="computeroutput"><span class="identifier">override__1</span></code>
|
|
(which is reserved in C++ because it contains double underscores <code class="computeroutput"><span class="identifier">__</span></code>). thus <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDE</span><span class="special">(</span><span class="identifier">override1</span><span class="special">,</span> <span class="identifier">_1</span><span class="special">)</span></code>
|
|
is used to name the type <code class="computeroutput"><span class="identifier">override1</span></code>
|
|
instead (see <a href="../../../example/features/named_override.cpp" target="_top"><code class="literal">named_override.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">positive_unary_pack</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">generic_unary_pack</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
|
<span class="special">:</span> <span class="identifier">BASES</span>
|
|
<span class="special">{</span>
|
|
<span class="keyword">public</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="comment">// BOOST_CONTRACT_OVERRIDE(_1) would generate reserved name `override__1`.</span>
|
|
<span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDE</span><span class="special">(</span><span class="identifier">override1</span><span class="special">,</span> <span class="identifier">_1</span><span class="special">)</span> <span class="comment">// Generate `override1`.</span>
|
|
|
|
<span class="keyword">virtual</span> <span class="keyword">void</span> <span class="identifier">_1</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="comment">/* override */</span> <span class="special">{</span>
|
|
<span class="comment">// Use `override1` generated by BOOST_CONTRACT_NAMED_OVERRIDE above.</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">override1</span><span class="special">>(</span>
|
|
<span class="identifier">v</span><span class="special">,</span>
|
|
<span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">void</span> <span class="special">(</span><span class="identifier">positive_unary_pack</span><span class="special">::*)(</span><span class="identifier">T</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">virtual_</span><span class="special">*)>(&</span><span class="identifier">positive_unary_pack</span><span class="special">::</span><span class="identifier">_1</span><span class="special">),</span>
|
|
<span class="keyword">this</span><span class="special">,</span>
|
|
<span class="identifier">value</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">value</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">value1_</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 <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>
|
|
macro can also be used when the name <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code> generated by <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
would clash with other names in user code, to generate names in CamelCase
|
|
or in any other preferred style, and in any other case when programmers need
|
|
or prefer to generate names different from <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code>.
|
|
</p>
|
|
<p>
|
|
Note that there is not a <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDES</span></code>
|
|
macro so <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>
|
|
needs to be invoked separately on each function name (there is instead a
|
|
<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDES.html" title="Macro BOOST_CONTRACT_OVERRIDES">BOOST_CONTRACT_OVERRIDES</a></code>
|
|
macro as seen in <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>). <a href="#ftn.boost_contract.advanced.named_overrides.f1" class="footnote" name="boost_contract.advanced.named_overrides.f1"><sup class="footnote">[63]</sup></a>
|
|
</p>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.access_specifiers"></a><a class="link" href="advanced.html#boost_contract.advanced.access_specifiers" title="Access Specifiers">Access Specifiers</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
As we have seen so far, programmers are required to decorate their classes
|
|
declaring the following extra members that are internally used by this library
|
|
to check contracts:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
The <code class="computeroutput"><span class="identifier">invariant</span></code> and <code class="computeroutput"><span class="identifier">static_invariant</span></code> member functions (used
|
|
to check class invariants, see <a class="link" href="tutorial.html#boost_contract.tutorial.class_invariants" title="Class Invariants">Class
|
|
Invariants</a>).
|
|
</li>
|
|
<li class="listitem">
|
|
The <code class="computeroutput"><span class="identifier">base_types</span></code> member
|
|
type declared via <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_BASE_TYPES.html" title="Macro BOOST_CONTRACT_BASE_TYPES">BOOST_CONTRACT_BASE_TYPES</a></code>
|
|
(used to implement subcontracting, see <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>).
|
|
</li>
|
|
<li class="listitem">
|
|
The <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code>
|
|
member types declared via <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_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDES.html" title="Macro BOOST_CONTRACT_OVERRIDES">BOOST_CONTRACT_OVERRIDES</a></code>
|
|
(used to implement subcontracting for overriding functions, see <a class="link" href="tutorial.html#boost_contract.tutorial.public_function_overrides__subcontracting_" title="Public Function Overrides (Subcontracting)">Public
|
|
Function Overrides</a>). <a href="#ftn.boost_contract.advanced.access_specifiers.f0" class="footnote" name="boost_contract.advanced.access_specifiers.f0"><sup class="footnote">[64]</sup></a>
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
In general, these members must be declared <code class="computeroutput"><span class="keyword">public</span></code>
|
|
in the user class in order for this library to be able to access them. <a href="#ftn.boost_contract.advanced.access_specifiers.f1" class="footnote" name="boost_contract.advanced.access_specifiers.f1"><sup class="footnote">[65]</sup></a> However, programmers might need to more precisely control the
|
|
public members of their classes to prevent incorrect access of encapsulated
|
|
members. All these members can be declared <code class="computeroutput"><span class="keyword">private</span></code>
|
|
as long as the <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code>
|
|
class is declared as <code class="computeroutput"><span class="keyword">friend</span></code>
|
|
of the user class. For example (see <a href="../../../example/features/access.cpp" target="_top"><code class="literal">access.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="preprocessor">#define</span> <span class="identifier">BASES</span> <span class="keyword">public</span> <span class="identifier">pushable</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span>
|
|
<span class="special">:</span> <span class="identifier">BASES</span>
|
|
<span class="special">{</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="comment">// Friend `access` class so...</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="comment">// ...private bases.</span>
|
|
<span class="preprocessor">#undef</span> <span class="identifier">BASES</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">// ...private invariants.</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="identifier">BOOST_CONTRACT_OVERRIDE</span><span class="special">(</span><span class="identifier">push_back</span><span class="special">)</span> <span class="comment">// ...private overrides.</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="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="comment">/* override */</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">override_push_back</span><span class="special">>(</span><span class="identifier">v</span><span class="special">,</span> <span class="special">&</span><span class="identifier">vector</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">value</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">max_size</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">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>
|
|
This technique is not used in most examples of this documentation only for
|
|
brevity, but programmers are encouraged to use it in real code.
|
|
</p>
|
|
<div class="warning"><table border="0" summary="Warning">
|
|
<tr>
|
|
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/src/images/warning.png"></td>
|
|
<th align="left">Warning</th>
|
|
</tr>
|
|
<tr><td align="left" valign="top"><p>
|
|
Not declaring <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code>
|
|
friend of user classes might cause compiler errors on some compilers (e.g.,
|
|
MSVC) because the private members needed to check the contracts will not
|
|
be accessible. On other compilers (e.g., GCC and Clang), the private access
|
|
level will instead fail SFINAE and no compiler error will be reported while
|
|
invariants and subcontracting will be silently skipped at run-time. Therefore,
|
|
programmers should always make sure to either declare invariant functions
|
|
and base types <code class="computeroutput"><span class="keyword">typedef</span></code> as
|
|
public members or to declare <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code>
|
|
as friend.
|
|
</p></td></tr>
|
|
</table></div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="boost_contract.advanced.throw_on_failures__and__noexcept__"></a><a class="link" href="advanced.html#boost_contract.advanced.throw_on_failures__and__noexcept__" title="Throw on Failures (and noexcept)">Throw
|
|
on Failures (and <code class="computeroutput"><span class="keyword">noexcept</span></code>)</a>
|
|
</h3></div></div></div>
|
|
<p>
|
|
If a condition checked using <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
is evaluated to be false or, more in general, if any of the specified contract
|
|
code throws an exception (<code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
simply expands to code that throws a <code class="computeroutput"><a class="link" href="../boost/contract/assertion_failure.html" title="Class assertion_failure">boost::contract::assertion_failure</a></code>
|
|
exception, 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>), this library will call an appropriate <span class="emphasis"><em>contract
|
|
failure handler</em></span> function as follow:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Preconditions: False <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
assertions and exceptions thrown from within <code class="computeroutput"><span class="special">.</span><span class="identifier">precondition</span><span class="special">(...)</span></code>
|
|
call <code class="computeroutput"><a class="link" href="../boost/contract/precondition_failure.html" title="Function precondition_failure">boost::contract::precondition_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Postconditions: False <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
assertions and exceptions thrown from within <code class="computeroutput"><span class="special">.</span><span class="identifier">postcondition</span><span class="special">(...)</span></code>
|
|
call <code class="computeroutput"><a class="link" href="../boost/contract/postcondition_failure.html" title="Function postcondition_failure">boost::contract::postcondition_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Exceptions guarantees: False <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
assertions and exceptions thrown from within <code class="computeroutput"><span class="special">.</span><span class="identifier">except</span><span class="special">(...)</span></code>
|
|
call <code class="computeroutput"><a class="link" href="../boost/contract/except_failure.html" title="Function except_failure">boost::contract::except_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Class invariants: False <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
assertions and exceptions thrown from <code class="computeroutput"><span class="identifier">invariant</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">static_invariant</span><span class="special">()</span></code> call <code class="computeroutput"><a class="link" href="../boost/contract/entry_invariant_failure.html" title="Function entry_invariant_failure">boost::contract::entry_invariant_failure</a></code>
|
|
when checked at function entry and <code class="computeroutput"><a class="link" href="../boost/contract/exit_invariant_failure.html" title="Function exit_invariant_failure">boost::contract::exit_invariant_failure</a></code>
|
|
when checked at function exit.
|
|
</li>
|
|
<li class="listitem">
|
|
Old value copies at body: Exceptions thrown from old value copies at
|
|
body within <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code> call <code class="computeroutput"><a class="link" href="../boost/contract/old_failure.html" title="Function old_failure">boost::contract::old_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Implementation checks: False <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>
|
|
assertions and exceptions thrown from implementation checks <code class="computeroutput"><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> </code><code class="literal"><span class="emphasis"><em>nullary-functor</em></span></code>
|
|
and <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">(...)</span></code> call <code class="computeroutput"><a class="link" href="../boost/contract/check_failure.html" title="Function check_failure">boost::contract::check_failure</a></code>.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
By default, these contract failure handlers print a message to the standard
|
|
error <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span></code> and then terminate the program calling
|
|
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span></code>. <a href="#ftn.boost_contract.advanced.throw_on_failures__and__noexcept__.f0" class="footnote" name="boost_contract.advanced.throw_on_failures__and__noexcept__.f0"><sup class="footnote">[66]</sup></a> However, programmers can override the default contract failure
|
|
handlers to perform any custom action on contract failure using the following
|
|
functions respectively:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
Preconditions: <code class="computeroutput"><a class="link" href="../boost/contract/set_precondition_failure.html" title="Function set_precondition_failure">boost::contract::set_precondition_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Postconditions: <code class="computeroutput"><a class="link" href="../boost/contract/set_postcondition_failure.html" title="Function set_postcondition_failure">boost::contract::set_postcondition_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Exception guarantees: <code class="computeroutput"><a class="link" href="../boost/contract/set_except_failure.html" title="Function set_except_failure">boost::contract::set_except_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Class invariants: <code class="computeroutput"><a class="link" href="../boost/contract/set_entr_idm45123870191120.html" title="Function set_entry_invariant_failure">boost::contract::set_entry_invariant_failure</a></code>
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/set_exit_invariant_failure.html" title="Function set_exit_invariant_failure">boost::contract::set_exit_invariant_failure</a></code>,
|
|
or <code class="computeroutput"><a class="link" href="../boost/contract/set_invariant_failure.html" title="Function set_invariant_failure">boost::contract::set_invariant_failure</a></code>
|
|
(to set both entry and exit invariant failure handlers at once for convenience).
|
|
</li>
|
|
<li class="listitem">
|
|
Old value copies at body: <code class="computeroutput"><a class="link" href="../boost/contract/set_old_failure.html" title="Function set_old_failure">boost::contract::set_old_failure</a></code>.
|
|
</li>
|
|
<li class="listitem">
|
|
Implementation checks: <code class="computeroutput"><a class="link" href="../boost/contract/set_check_failure.html" title="Function set_check_failure">boost::contract::set_check_failure</a></code>.
|
|
</li>
|
|
</ul></div>
|
|
<p>
|
|
These <code class="computeroutput"><span class="identifier">set_</span><span class="special">...</span><span class="identifier">_failure</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>f</em></span></code><code class="computeroutput"><span class="special">)</span></code> function calls return the contract failure
|
|
handler functor <code class="literal"><span class="emphasis"><em>f</em></span></code> that they take
|
|
as input parameter. <a href="#ftn.boost_contract.advanced.throw_on_failures__and__noexcept__.f1" class="footnote" name="boost_contract.advanced.throw_on_failures__and__noexcept__.f1"><sup class="footnote">[67]</sup></a> For example (see <a href="../../../example/features/throw_on_failure.cpp" target="_top"><code class="literal">throw_on_failure.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">main</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">set_precondition_failure</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">set_postcondition_failure</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">set_invariant_failure</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">set_old_failure</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">from</span> <span class="identifier">where</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">where</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">from_destructor</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// Shall not throw from C++ destructors.</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">clog</span> <span class="special"><<</span> <span class="string">"ignored destructor contract failure"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="special">}</span> <span class="keyword">else</span> <span class="keyword">throw</span><span class="special">;</span> <span class="comment">// Re-throw (assertion_failure, user-defined, etc.).</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">set_except_failure</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">from</span> <span class="identifier">where</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="comment">// Already an active exception so shall not throw another...</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">clog</span> <span class="special"><<</span> <span class="string">"ignored exception guarantee failure"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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">set_check_failure</span><span class="special">(</span>
|
|
<span class="special">[]</span> <span class="special">{</span>
|
|
<span class="comment">// But now CHECK shall not be used in destructor implementations.</span>
|
|
<span class="keyword">throw</span><span class="special">;</span> <span class="comment">// Re-throw (assertion_failure, user-defined, etc.).</span>
|
|
<span class="special">}</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
When programming custom failure handlers that trow exceptions instead of
|
|
terminating the program, programmers should be wary of the following:
|
|
</p>
|
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
|
<li class="listitem">
|
|
In order to comply with C++ and STL exception safety, destructors should
|
|
never throw (in fact destructors are implicitly declared <code class="computeroutput"><span class="keyword">noexcept</span></code> since C++11). This library passes
|
|
a <code class="computeroutput"><a class="link" href="../boost/contract/from.html" title="Type from">boost::contract::from</a></code>
|
|
parameter to the contract failure handlers for preconditions, postconditions,
|
|
class invariants, and old value copies at body (see <code class="computeroutput"><a class="link" href="../boost/contract/precondition_failure.html" title="Function precondition_failure">boost::contract::precondition_failure</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/postcondition_failure.html" title="Function postcondition_failure">boost::contract::postcondition_failure</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/entry_invariant_failure.html" title="Function entry_invariant_failure">boost::contract::entry_invariant_failure</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/exit_invariant_failure.html" title="Function exit_invariant_failure">boost::contract::exit_invariant_failure</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/old_failure.html" title="Function old_failure">boost::contract::old_failure</a></code>
|
|
respectively). This <code class="computeroutput"><a class="link" href="../boost/contract/from.html" title="Type from">boost::contract::from</a></code>
|
|
parameter indicates if the contract failure occurred in a destructor,
|
|
constructor, or function call so programmers can use it to code custom
|
|
contract failure hander functions that never throw from destructors.
|
|
(In the example above, contract failures from destructors are simply
|
|
ignored even if that is probably never a safe thing to do in real code.)
|
|
</li>
|
|
<li class="listitem">
|
|
C++ stack-unwinding will execute base class destructors even when the
|
|
derived class destructor trows an exception. Therefore, the contracts
|
|
of base class destructors will continue to be checked when contract failure
|
|
handlers are programmed to throw exceptions on contract failures from
|
|
destructors (yet another reason not to throw exceptions from destructors,
|
|
not even because of contract failures).
|
|
</li>
|
|
<li class="listitem">
|
|
Implementation checks can appear in any code, including destructor implementation
|
|
code, so <code class="computeroutput"><a class="link" href="../boost/contract/check_failure.html" title="Function check_failure">boost::contract::check_failure</a></code>
|
|
should also never throw, or implementation checks should never be used
|
|
in destructors otherwise these destructors will throw (note that <code class="computeroutput"><a class="link" href="../boost/contract/check_failure.html" title="Function check_failure">boost::contract::check_failure</a></code>
|
|
does not provide the <code class="computeroutput"><a class="link" href="../boost/contract/from.html" title="Type from">boost::contract::from</a></code>
|
|
parameter so it is not possible to differentiate from implementation
|
|
checks failing from destructors instead than from other parts of the
|
|
code).
|
|
</li>
|
|
<li class="listitem">
|
|
The contract failure handler for exception guarantees <code class="computeroutput"><a class="link" href="../boost/contract/except_failure.html" title="Function except_failure">boost::contract::except_failure</a></code>
|
|
should never throw (regardless of the value of its <code class="computeroutput"><a class="link" href="../boost/contract/from.html" title="Type from">boost::contract::from</a></code>
|
|
parameter) because when <code class="computeroutput"><a class="link" href="../boost/contract/except_failure.html" title="Function except_failure">boost::contract::except_failure</a></code>
|
|
is called there is already an active exception on the stack, the exception
|
|
that triggered the exception guarantees to be checked in the first place
|
|
(throwing an exception while there is already an active exception will
|
|
force program termination or lead to undefined behaviour in C++).
|
|
</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>
|
|
It is the responsibility of the programmers to decide how to handle contract
|
|
failures from destructors when they program custom contract failure handlers
|
|
that throw exceptions instead of terminating the program (given that C++
|
|
and STL exception safety rules requires destructors to never throw). This
|
|
is not a simple dilemma and it might be a good reason to terminate the
|
|
program instead of throwing exceptions when assertions fail in C++ (as
|
|
this library and also C-style <code class="computeroutput"><span class="identifier">assert</span></code>
|
|
do by default).
|
|
</p></td></tr>
|
|
</table></div>
|
|
<p>
|
|
Contract assertions can be programmed to throw <code class="computeroutput"><a class="link" href="../boost/contract/assertion_failure.html" title="Class assertion_failure">boost::contract::assertion_failure</a></code>
|
|
using <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span></code><code class="literal"><span class="emphasis"><em>condition</em></span></code><code class="computeroutput"><span class="special">)</span></code> as we have seen so far (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>). Alternatively, contract assertions can be programmed to throw
|
|
any other exception (including user-defined exceptions) using code similar
|
|
to the following:
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">if</span><span class="special">(!</span><code class="literal"><span class="emphasis"><em>condition</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>
|
|
For example, the following precondition functor throws <code class="computeroutput">boost::contract:assertion_failure</code>
|
|
(via <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_ASSERT.html" title="Macro BOOST_CONTRACT_ASSERT">BOOST_CONTRACT_ASSERT</a></code>)
|
|
on its first assertion and the user-defined exception <code class="computeroutput"><span class="identifier">too_large_error</span></code>
|
|
on its second assertion (both exceptions will cause this library to call
|
|
the customized <code class="computeroutput"><a class="link" href="../boost/contract/precondition_failure.html" title="Function precondition_failure">boost::contract::precondition_failure</a></code>
|
|
listed above which will in turn re-throw the exceptions up he stack, see
|
|
<a href="../../../example/features/throw_on_failure.cpp" target="_top"><code class="literal">throw_on_failure.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">too_large_error</span> <span class="special">{};</span>
|
|
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">unsigned</span> <span class="identifier">MaxSize</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">cstring</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</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">cstring</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="identifier">MaxSize</span><span class="special">></span> <span class="special">></span>
|
|
<span class="special">:</span> <span class="identifier">BASES</span>
|
|
<span class="special">{</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">public</span><span class="special">:</span>
|
|
<span class="comment">/* implicit */</span> <span class="identifier">cstring</span><span class="special">(</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">chars</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">cstring</span><span class="special">>([&]</span> <span class="special">{</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">chars</span><span class="special">);</span> <span class="comment">// Throw `assertion_failure`.</span>
|
|
<span class="comment">// Or, throw user-defined exception.</span>
|
|
<span class="keyword">if</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">strlen</span><span class="special">(</span><span class="identifier">chars</span><span class="special">)</span> <span class="special">></span> <span class="identifier">MaxSize</span><span class="special">)</span> <span class="keyword">throw</span> <span class="identifier">too_large_error</span><span class="special">();</span>
|
|
<span class="special">})</span>
|
|
<span class="special">{</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"> <span class="comment">/* ... */</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
Finally, note that the exception specifiers <code class="computeroutput"><span class="keyword">noexcept</span></code>
|
|
(since C++11) and <code class="computeroutput"><span class="keyword">throw</span></code> (deprecated
|
|
in C++11) of the enclosing operation declaring the contract correctly apply
|
|
to the contract code as well. Therefore, even if the contract failure handlers
|
|
are reprogrammed to throw exceptions in case of contract failures, those
|
|
exceptions will never be thrown outside the context of the enclosing operation
|
|
if that is not in accordance with the exception specifiers of that operation
|
|
(specifically, note that all destructors are implicitly declared <code class="computeroutput"><span class="keyword">noexcept</span></code> in C++11). For example, the following
|
|
code will correctly never throw from the <code class="computeroutput"><span class="keyword">noexcept</span></code>
|
|
destructor, not even if the class invariants checked at destructor entry
|
|
throw <code class="computeroutput"><span class="identifier">too_large_error</span></code> and
|
|
the contract failure handlers for invariants are programmed to throw from
|
|
destructors (the program will always terminate in this case instead, see
|
|
<a href="../../../example/features/throw_on_failure.cpp" target="_top"><code class="literal">throw_on_failure.cpp</code></a>):
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">too_large_error</span> <span class="special">{};</span>
|
|
|
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">unsigned</span> <span class="identifier">MaxSize</span><span class="special">></span>
|
|
<span class="keyword">class</span> <span class="identifier">cstring</span>
|
|
<span class="preprocessor">#define</span> <span class="identifier">BASES</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">cstring</span><span class="special"><</span> <span class="special">\</span>
|
|
<span class="identifier">MaxSize</span><span class="special">></span> <span class="special">></span>
|
|
<span class="special">:</span> <span class="identifier">BASES</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">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">size</span><span class="special">()</span> <span class="special">></span> <span class="identifier">MaxSize</span><span class="special">)</span> <span class="keyword">throw</span> <span class="identifier">too_large_error</span><span class="special">();</span> <span class="comment">// Throw user-defined ex.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">chars_</span><span class="special">);</span> <span class="comment">// Or, throw `assertion_failure`.</span>
|
|
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">(</span><span class="identifier">chars_</span><span class="special">[</span><span class="identifier">size</span><span class="special">()]</span> <span class="special">==</span> <span class="char">'\0'</span><span class="special">);</span>
|
|
<span class="special">}</span>
|
|
|
|
<span class="special">~</span><span class="identifier">cstring</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">{</span> <span class="comment">// Exception specifiers apply to contract code.</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="special">}</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"> <span class="comment">/* ... */</span>
|
|
<span class="special">};</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
<pre class="programlisting"><span class="comment">/* ... */</span>
|
|
|
|
<span class="comment">// Warning... might cause destructors to throw (unless declared noexcept).</span>
|
|
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">contract</span><span class="special">::</span><span class="identifier">set_invariant_failure</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">from</span><span class="special">)</span> <span class="special">{</span>
|
|
<span class="keyword">throw</span><span class="special">;</span> <span class="comment">// Throw no matter if from destructor, etc.</span>
|
|
<span class="special">}</span>
|
|
<span class="special">);</span>
|
|
|
|
<span class="comment">/* ... */</span>
|
|
</pre>
|
|
<p>
|
|
</p>
|
|
</div>
|
|
<div class="footnotes">
|
|
<br><hr style="width:100; text-align:left;margin-left: 0">
|
|
<div id="ftn.boost_contract.advanced.pure_virtual_public_functions.f0" class="footnote"><p><a href="#boost_contract.advanced.pure_virtual_public_functions.f0" class="para"><sup class="para">[52] </sup></a>
|
|
This consequence of the <a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle" target="_top">substitution
|
|
principle</a> <span class="quote">“<span class="quote">that if any function in an inheritance hierarchy
|
|
has no preconditions, then preconditions on functions overriding it have
|
|
no useful effect</span>”</span> is also explicitly mentioned in the contract documentation
|
|
of the D Programming Language (see <a class="link" href="bibliography.html#Bright04_anchor">[Bright04]</a>).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.optional_return_values.f0" class="footnote"><p><a href="#boost_contract.advanced.optional_return_values.f0" class="para"><sup class="para">[53] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> This library uses <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code> instead of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span></code>
|
|
because <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span></code> is not available before C++17.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.optional_return_values.f1" class="footnote"><p><a href="#boost_contract.advanced.optional_return_values.f1" class="para"><sup class="para">[54] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> This library requires the postcondition
|
|
functor parameter to be of type <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><...</span> <span class="keyword">const</span><span class="special">&></span></code> so the return value does not have
|
|
to be copied (because of <code class="computeroutput"><span class="special">&</span></code>)
|
|
while postconditions are still not allowed to change its value (because
|
|
of <code class="computeroutput"><span class="keyword">const</span></code>, see <a class="link" href="contract_programming_overview.html#boost_contract.contract_programming_overview.constant_correctness" title="Constant-Correctness">Constant-Correctness</a>).
|
|
In addition, programmers are encouraged to declare the postcondition functor
|
|
to take its argument also as a constant reference <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><...</span> <span class="keyword">const</span><span class="special">&></span> <span class="keyword">const</span><span class="special">&</span></code> to avoid possibly expensive copies
|
|
of the <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code> type itself.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.private_and_protected_functions.f0" class="footnote"><p><a href="#boost_contract.advanced.private_and_protected_functions.f0" class="para"><sup class="para">[55] </sup></a>
|
|
Technically, the extra virtual parameter can still be passed to <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OLDOF.html" title="Macro BOOST_CONTRACT_OLDOF">BOOST_CONTRACT_OLDOF</a></code> but that is
|
|
not necessary and it has no effect so it is not done in this documentation.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.friend_functions.f0" class="footnote"><p><a href="#boost_contract.advanced.friend_functions.f0" class="para"><sup class="para">[56] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> Contract programming proposals
|
|
for C++ like <a class="link" href="bibliography.html#N1962_anchor">[N1962]</a> do not provide
|
|
a mechanism for friend functions to check class invariants of objects passed
|
|
as parameters. In other words, these proposals do not enable contracts
|
|
to recognize that in C++ some friend functions logically act as if they
|
|
were part of the public interface of the objects they take as parameters.
|
|
This is reasonable for proposals that add contracts to the core language
|
|
because friend functions are not always meant to extend an object public
|
|
interface and C++ does not provide a mechanism to programmatically specify
|
|
when they do and when they do not. However, this library adds the flexibility
|
|
to let programmers manually specify when friend functions should also check
|
|
class invariants of the objects they take as parameters (using <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>)
|
|
and when they should not (using <code class="computeroutput"><a class="link" href="../boost/contract/function.html" title="Function function">boost::contract::function</a></code>
|
|
instead).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.function_overloads.f0" class="footnote"><p><a href="#boost_contract.advanced.function_overloads.f0" class="para"><sup class="para">[57] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> In order to avoid copies, this
|
|
library takes all function arguments and the return value passed to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>
|
|
as references when used within public function overrides. Therefore, the
|
|
library cannot differentiate when the actual function argument and return
|
|
types are passed by reference and when they are not. As a result, the library
|
|
cannot automatically reconstruct the type of the enclosing public function
|
|
so this type must be deduced from the function pointer passed by programmers
|
|
to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45123869756752.html" title="Function template public_function">boost::contract::public_function</a></code>.
|
|
When this automatic deduction is not possible due to overloaded function
|
|
names, programmers must explicitly use <code class="computeroutput"><span class="keyword">static_cast</span></code>
|
|
to resolve ambiguities as usual in C++ with pointers to overloaded functions.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__.f0" class="footnote"><p><a href="#boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__.f0" class="para"><sup class="para">[58] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> In general, it might be useful
|
|
to specify contracts for <code class="computeroutput"><span class="keyword">constexpr</span></code>
|
|
functions and literal classes. However, the implementation of this library
|
|
cannot support contracts for <code class="computeroutput"><span class="keyword">constexpr</span></code>
|
|
functions and classes because C++ does not currently allow <code class="computeroutput"><span class="keyword">constexpr</span></code> functions to do the following:
|
|
Declare local variables of (literal) types with non-trivial <code class="computeroutput"><span class="keyword">constexpr</span></code> destructors (this RAII technique
|
|
is used by this library to check invariants, postconditions, and exceptions
|
|
guarantees at exit); Call other <code class="computeroutput"><span class="keyword">constexpr</span></code>
|
|
functions using try-catch statements (used by this library to report contract
|
|
assertion failures and catch any other exception that might be thrown when
|
|
evaluating the asserted conditions); Use lambda functions (used by this
|
|
library for convenience to program functors that that check preconditions,
|
|
postconditions, and exception guarantees). Also note that even if supported,
|
|
contracts for <code class="computeroutput"><span class="keyword">constexpr</span></code> functions
|
|
probably would not use old values (because <code class="computeroutput"><span class="keyword">constexpr</span></code>
|
|
prevents functions from having any side effect visible to the caller and
|
|
variables recording such side-effects are usually the candidates for old
|
|
value copies) and subcontracting (because <code class="computeroutput"><span class="keyword">constexpr</span></code>
|
|
functions cannot be virtual).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.implementation_checks.f0" class="footnote"><p><a href="#boost_contract.advanced.implementation_checks.f0" class="para"><sup class="para">[59] </sup></a>
|
|
Of course, nothing prevents programmers from calling functors to specify
|
|
boolean conditions when if-guards and other statements are required to
|
|
assert the implementation checks. For example, programmers can use C++11
|
|
lambda functions to define and call such functors in place where the implementation
|
|
checks are specified <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">([...]</span> <span class="special">-></span> <span class="keyword">bool</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span> <span class="special">())</span></code>.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.old_value_copies_at_body.f0" class="footnote"><p><a href="#boost_contract.advanced.old_value_copies_at_body.f0" class="para"><sup class="para">[60] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> Functors for preconditions,
|
|
old value assignments, postconditions, and exception guarantees are all
|
|
optional but when specified, they must be specified in that order. Such
|
|
order is enforced by the fact that <code class="computeroutput"><a class="link" href="../boost/contract/specify__idm45123870039968.html" title="Class template specify_precondition_old_postcondition_except">boost::contract::specify_precondition_old_postcondition_except</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/specify__idm45123870103104.html" title="Class template specify_old_postcondition_except">boost::contract::specify_old_postcondition_except</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/specify__idm45123870066880.html" title="Class template specify_postcondition_except">boost::contract::specify_postcondition_except</a></code>,
|
|
<code class="computeroutput"><a class="link" href="../boost/contract/specify_except.html" title="Class specify_except">boost::contract::specify_except</a></code>,
|
|
and <code class="computeroutput"><a class="link" href="../boost/contract/specify_nothing.html" title="Class specify_nothing">boost::contract::specify_nothing</a></code>
|
|
provide a progressively smaller subset of their <code class="computeroutput"><span class="special">.</span><span class="identifier">precondition</span><span class="special">(...)</span></code>,
|
|
<code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>, <code class="computeroutput"><span class="special">.</span><span class="identifier">postcondition</span><span class="special">(...)</span></code>,
|
|
and <code class="computeroutput"><span class="special">.</span><span class="identifier">except</span><span class="special">(...)</span></code> member functions. The enforced order
|
|
for specifying preconditions, old value assignments, postconditions, and
|
|
exception guarantees makes logical sense because it follows the order at
|
|
which these are executed at run-time. Other contract programming frameworks
|
|
allow to mix this order, that could have been implemented for this library
|
|
as well but it would have complicated somewhat the library implementation
|
|
while adding no real value (arguably creating confusion in user code by
|
|
not enforcing a consistent order for specifying contract conditions).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.old_value_copies_at_body.f1" class="footnote"><p><a href="#boost_contract.advanced.old_value_copies_at_body.f1" class="para"><sup class="para">[61] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> It would be possible for
|
|
this library to internally wrap all old value operations (<code class="computeroutput"><a class="link" href="../boost/contract/old_ptr.html" title="Class template old_ptr">boost::contract::old_ptr</a></code> copy
|
|
constructor, <code class="computeroutput"><a class="link" href="../boost/contract/make_old_idm45123869837456.html" title="Function make_old">boost::contract::make_old</a></code>,
|
|
etc.) with try-catch statements so to call <code class="computeroutput"><a class="link" href="../boost/contract/old_failure.html" title="Function old_failure">boost::contract::old_failure</a></code>
|
|
also when old values are copied when they are constructed outside <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code>. However, that will prevent this
|
|
library from knowing the <code class="computeroutput"><a class="link" href="../boost/contract/from.html" title="Type from">boost::contract::from</a></code>
|
|
parameter and that would be problematic (specifically because destructors
|
|
can have postconditions so that parameter is necessary to make sure user-defined
|
|
failure handlers can be programmed to never throw from destructors as
|
|
C++ usually requires).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.named_overrides.f0" class="footnote"><p><a href="#boost_contract.advanced.named_overrides.f0" class="para"><sup class="para">[62] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> A different macro <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>
|
|
is used instead of overloading <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
using variadic macros because the override macro cannot be programmed manually
|
|
by users so making it a variadic would prevent to use this library on compilers
|
|
that do not support variadic macros (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>).
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.named_overrides.f1" class="footnote"><p><a href="#boost_contract.advanced.named_overrides.f1" class="para"><sup class="para">[63] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> The syntax for invoking a possible
|
|
<code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDES</span></code>
|
|
macro would need to be something like <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDES</span><span class="special">(</span><span class="identifier">type_name1</span><span class="special">,</span> <span class="identifier">func_name1</span><span class="special">,</span> <span class="identifier">type_name2</span><span class="special">,</span> <span class="identifier">func_name2</span><span class="special">,</span> <span class="special">...)</span></code>.
|
|
The authors found such a syntax less readable than repeating single <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45123869781472.html" title="Macro BOOST_CONTRACT_NAMED_OVERRIDE">BOOST_CONTRACT_NAMED_OVERRIDE</a></code>
|
|
invocations as in <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDE</span><span class="special">(</span><span class="identifier">type_name1</span><span class="special">,</span> <span class="identifier">func_name1</span><span class="special">)</span> <span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDE</span><span class="special">(</span><span class="identifier">type_name2</span><span class="special">,</span> <span class="identifier">func_name2</span><span class="special">)</span> <span class="special">...</span></code> so
|
|
decided not to provide the <code class="computeroutput"><span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDES</span></code>
|
|
macro.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.access_specifiers.f0" class="footnote"><p><a href="#boost_contract.advanced.access_specifiers.f0" class="para"><sup class="para">[64] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> The internals of the <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code>
|
|
type generated by <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_OVERRIDE.html" title="Macro BOOST_CONTRACT_OVERRIDE">BOOST_CONTRACT_OVERRIDE</a></code>
|
|
use names reserved by this library so programmers should not actually
|
|
use such a type even when it is declared <code class="computeroutput"><span class="keyword">public</span></code>.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.access_specifiers.f1" class="footnote"><p><a href="#boost_contract.advanced.access_specifiers.f1" class="para"><sup class="para">[65] </sup></a>
|
|
There is some variability among compiler implementations: The <code class="computeroutput"><span class="identifier">base_types</span></code> member type needs to be declared
|
|
<code class="computeroutput"><span class="keyword">public</span></code> on MSVC, GCC, and Clang;
|
|
The <code class="computeroutput"><span class="identifier">invariant</span></code> and <code class="computeroutput"><span class="identifier">static_invariant</span></code> member functions need
|
|
to be declared <code class="computeroutput"><span class="keyword">public</span></code> on MSVC,
|
|
but not on GCC and Clang; The <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code> member types do not have to be declared
|
|
<code class="computeroutput"><span class="keyword">public</span></code> on any compiler. In
|
|
any case, declaring the <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code>
|
|
class <code class="computeroutput"><span class="keyword">friend</span></code> as shown in this
|
|
section allows to always declare the extra members <code class="computeroutput"><span class="keyword">private</span></code>
|
|
on all compilers.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.throw_on_failures__and__noexcept__.f0" class="footnote"><p><a href="#boost_contract.advanced.throw_on_failures__and__noexcept__.f0" class="para"><sup class="para">[66] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> In general, when a contract
|
|
fails the only safe thing to do is to terminate program execution (because
|
|
the contract failure indicates a bug in the program, and in general a buggy
|
|
program will be in a state for which no operation can be successfully performed,
|
|
so the program should be stopped as soon as possible). Therefore, this
|
|
library terminates the program by default. However, for specific applications,
|
|
programmers could implement some fail-safe mechanism for which some mission-critical
|
|
operation could always be performed upon handling failures so this library
|
|
allows programmers to override the default contract failure handlers to
|
|
fully customize how to handle contract failures.
|
|
</p></div>
|
|
<div id="ftn.boost_contract.advanced.throw_on_failures__and__noexcept__.f1" class="footnote"><p><a href="#boost_contract.advanced.throw_on_failures__and__noexcept__.f1" class="para"><sup class="para">[67] </sup></a>
|
|
<span class="bold"><strong>Rationale:</strong></span> The <code class="computeroutput"><span class="identifier">set_</span><span class="special">...</span><span class="identifier">_failure</span></code>
|
|
functions take a functor as parameter (to accept not just function pointers
|
|
but also lambdas, binds, etc.) and they return this same functor as result
|
|
so they can be concatenated (this interface is a bit different from <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">set_terminate</span></code>). The related <code class="computeroutput"><span class="identifier">get_</span><span class="special">...</span><span class="identifier">_failure</span></code> functions can be used to query
|
|
the functors currently set as failure handlers (this interface is similar
|
|
to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">get_terminate</span></code>).
|
|
</p></div>
|
|
</div>
|
|
</div>
|
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
|
<td align="left"></td>
|
|
<td align="right"><div class="copyright-footer">Copyright © 2008-2018 Lorenzo Caminiti<p>
|
|
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
|
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
|
</p>
|
|
</div></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="tutorial.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="extras.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|