1919 lines
229 KiB
HTML
1919 lines
229 KiB
HTML
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<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_values_copied_at_body">Old
|
||
Values Copied 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 usage 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_idm45028038882752.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):
|
||
</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>. <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> In other words, the code above has the same 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 also 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> real
|
||
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> <code class="computeroutput"><span class="keyword">return</span></code>
|
||
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><code class="literal"><span class="emphasis"><em>return-type</em></span></code><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> <code class="literal"><span class="emphasis"><em>return-expression</em></span></code><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_idm45028038882752.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 use (from within the class,
|
||
base classes, friend classes or functions, etc.). When programmers decide
|
||
to specify contracts for private and protected functions, they can 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_idm45028038882752.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 <span class="emphasis"><em>public</em></span> 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_idm45028038882752.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
|
||
(at least up to Visual Studio 2015), 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>
|
||
In general, 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>
|
||
is used to program their contracts 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_idm45028038882752.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">postex</span> <span 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_idm45028038882752.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 that 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_idm45028038882752.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_idm45028038882752.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_idm45028038882752.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_idm45028038882752.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_idm45028038882752.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">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">max</span><span class="special">()</span> <span class="special">-</span> <span class="identifier">x</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="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">i</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>
|
||
The 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 also a mechanism to check assertions within implementation
|
||
code (differently from preconditions, postconditions, exceptions guarantees,
|
||
and class invariants that are instead checked before or after code that implements
|
||
a function body). These <span class="emphasis"><em>implementation checks</em></span> 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_idm45028038882752.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 for its assertions. These variables can be captured by value when the
|
||
overhead of copying such variables is acceptable. In any case, programmers
|
||
should not write implementation checks that 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 (note
|
||
that 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><code class="literal"><span class="emphasis"><em>boolean-condition</em></span></code><span class="special">)</span>
|
||
<span class="comment">// Or, if `boolean-condition` contains commas `,` not already within parenthesis `()`...</span>
|
||
<span class="identifier">BOOST_CONTRACT_ASSERT</span><span class="special">((</span><code class="literal"><span class="emphasis"><em>boolean-condition</em></span></code><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 or, 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 disabled 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 (see <a class="link" href="extras.html#boost_contract.extras.disable_contract_checking" title="Disable Contract Checking">Disable
|
||
Contract Checking</a>). 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 overheads 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 (note that this is not a variadic macro):
|
||
</p>
|
||
<pre class="programlisting"><span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">(</span><code class="literal"><span class="emphasis"><em>boolean-condition</em></span></code><span class="special">)</span>
|
||
<span class="comment">// Or, if `boolean-condition` contains commas `,` not already within parenthesis `()`...</span>
|
||
<span class="identifier">BOOST_CONTRACT_CHECK</span><span class="special">((</span><code class="literal"><span class="emphasis"><em>boolean-condition</em></span></code><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 it 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_idm45028039677008.html" title="Macro BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION">BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION</a></code>).
|
||
</li>
|
||
</ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="boost_contract.advanced.old_values_copied_at_body"></a><a class="link" href="advanced.html#boost_contract.advanced.old_values_copied_at_body" title="Old Values Copied at Body">Old
|
||
Values Copied 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. That 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 speaking, old values should be copied before executing the function
|
||
body but <span class="emphasis"><em>after</em></span> checking class invariants and preconditions
|
||
at function entry (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 specified by <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_values_copied_at_body.f0" class="footnote" name="boost_contract.advanced.old_values_copied_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 the 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_char</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_char</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_char</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_char</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 the variables that
|
||
it needs to evaluate 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 copy the values the captured variables will have
|
||
just before executing the function body, and not 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, programmers should write the functor passed
|
||
to <code class="computeroutput"><span class="special">.</span><span class="identifier">old</span><span class="special">(...)</span></code> so that it modifies only old values
|
||
and not the values of other 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>
|
||
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_values_copied_at_body.f1" class="footnote" name="boost_contract.advanced.old_values_copied_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 the type <code class="computeroutput"><span class="identifier">override_</span><span class="special">...</span></code> that is passed as an explicit template
|
||
parameter to <code class="computeroutput"><a class="link" href="../boost/contract/public_f_idm45028038882752.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> (because all symbols containing double
|
||
underscores <code class="computeroutput"><span class="special">...</span><span class="identifier">__</span><span class="special">...</span></code> are reserved symbols in the C++ standard).
|
||
There is a separate macro <code class="computeroutput"><a class="link" href="../BOOST_CO_idm45028038910320.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><code class="literal"><span class="emphasis"><em>function-name</em></span></code><span class="special">)</span> <span class="comment">// Generate `override_...`.</span>
|
||
<span class="identifier">BOOST_CONTRACT_NAMED_OVERRIDE</span><span class="special">(</span><code class="literal"><span class="emphasis"><em>type-name</em></span></code><span class="special">,</span> <code class="literal"><span class="emphasis"><em>function-name</em></span></code><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 symbol in C++ because it contains a double underscore
|
||
<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_idm45028038910320.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_idm45028038910320.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 seen thus far, this library requires programmers to decorate their classes
|
||
declaring the following extra members:
|
||
</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
|
||
<code class="computeroutput"><span class="keyword">typedef</span></code> 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_idm45028038910320.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="comment">// Private section of the class.</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="comment">// Public section of the class.</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. Programmers are encouraged to use <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code>
|
||
in real production code freely as they see fit.
|
||
</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 values copied at body: Exceptions thrown from old values copied 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_idm45028039331504.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 values copied 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 a reference to the
|
||
contract failure handler functor <code class="literal"><span class="emphasis"><em>f</em></span></code>
|
||
that they take as input parameter (so they can be concatenated). <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="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 values copied 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 production
|
||
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">
|
||
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>
|
||
<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>
|
||
</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>
|
||
Programmers need to decide how to handle contract failures from destructors
|
||
when they write 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>
|
||
<h5>
|
||
<a name="boost_contract.advanced.throw_on_failures__and__noexcept__.h0"></a>
|
||
<span class="phrase"><a name="boost_contract.advanced.throw_on_failures__and__noexcept__.throw_user_defined_exceptions"></a></span><a class="link" href="advanced.html#boost_contract.advanced.throw_on_failures__and__noexcept__.throw_user_defined_exceptions">Throw
|
||
User-Defined Exceptions</a>
|
||
</h5>
|
||
<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"><a class="link" href="../boost/contract/assertion_failure.html" title="Class assertion_failure">boost::contract::assertion_failure</a></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 the 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>
|
||
<h5>
|
||
<a name="boost_contract.advanced.throw_on_failures__and__noexcept__.h1"></a>
|
||
<span class="phrase"><a name="boost_contract.advanced.throw_on_failures__and__noexcept__.exception_specifiers___code__phrase_role__keyword__noexcept__phrase___code__and__code__phrase_role__keyword__throw__phrase___code___"></a></span><a class="link" href="advanced.html#boost_contract.advanced.throw_on_failures__and__noexcept__.exception_specifiers___code__phrase_role__keyword__noexcept__phrase___code__and__code__phrase_role__keyword__throw__phrase___code___">Exception
|
||
Specifiers (<code class="computeroutput"><span class="keyword">noexcept</span></code> and <code class="computeroutput"><span class="keyword">throw</span></code>`)</a>
|
||
</h5>
|
||
<p>
|
||
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 function, constructor, or destructor 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).
|
||
</p>
|
||
<p>
|
||
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>
|
||
to support a larger number of compilers and their versions (because <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">optional</span></code> was 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 provides 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_idm45028038882752.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_idm45028038882752.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_idm45028038882752.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 current 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 within <code class="computeroutput"><a class="link" href="../BOOST_CONTRACT_CHECK.html" title="Macro BOOST_CONTRACT_CHECK">BOOST_CONTRACT_CHECK</a></code> 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:
|
||
</p>
|
||
<pre class="programlisting"><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="keyword">if</span><span class="special">(</span><span class="identifier">even_numbers</span><span class="special">)</span> <span class="keyword">return</span> <span class="identifier">gcd</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">==</span> <span class="number">2</span><span class="special">;</span>
|
||
<span class="keyword">else</span> <span class="keyword">return</span> <span class="identifier">gcd</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</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>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
</div>
|
||
<div id="ftn.boost_contract.advanced.old_values_copied_at_body.f0" class="footnote"><p><a href="#boost_contract.advanced.old_values_copied_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__idm45028039176672.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__idm45028039243488.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__idm45028039205424.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_values_copied_at_body.f1" class="footnote"><p><a href="#boost_contract.advanced.old_values_copied_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_idm45028038966352.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_idm45028038910320.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_idm45028038910320.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> Note that 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 these extra members all <code class="computeroutput"><span class="keyword">public</span></code>
|
||
or all <code class="computeroutput"><span class="keyword">private</span></code> when the <code class="computeroutput"><a class="link" href="../boost/contract/access.html" title="Class access">boost::contract::access</a></code> class
|
||
is also declared <code class="computeroutput"><span class="keyword">friend</span></code> always
|
||
works 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 and
|
||
safely 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 operations 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-2019 Lorenzo Caminiti<p>
|
||
Distributed under the Boost Software License, Version 1.0 (see accompanying
|
||
file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||
</p>
|
||
</div></td>
|
||
</tr></table>
|
||
<hr>
|
||
<div class="spirit-nav">
|
||
<a accesskey="p" href="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>
|