1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918 |
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
- <title>Advanced</title>
- <link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
- <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
- <link rel="home" href="../index.html" title="Chapter 1. Boost.Contract 1.0.0">
- <link rel="up" href="../index.html" title="Chapter 1. Boost.Contract 1.0.0">
- <link rel="prev" href="tutorial.html" title="Tutorial">
- <link rel="next" href="extras.html" title="Extras">
- </head>
- <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
- <table cellpadding="2" width="100%"><tr>
- <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
- <td align="center"><a href="../../../../../index.html">Home</a></td>
- <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
- <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
- <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
- <td align="center"><a href="../../../../../more/index.htm">More</a></td>
- </tr></table>
- <hr>
- <div class="spirit-nav">
- <a accesskey="p" href="tutorial.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="extras.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
- </div>
- <div class="section">
- <div class="titlepage"><div><div><h2 class="title" style="clear: both">
- <a name="boost_contract.advanced"></a><a class="link" href="advanced.html" title="Advanced">Advanced</a>
- </h2></div></div></div>
- <div class="toc"><dl class="toc">
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.pure_virtual_public_functions">Pure
- Virtual Public Functions</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.optional_return_values">Optional
- Return Values</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.private_and_protected_functions">Private
- and Protected Functions</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.friend_functions">Friend Functions</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.function_overloads">Function
- Overloads</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.lambdas__loops__code_blocks__and__constexpr__">Lambdas,
- Loops, Code Blocks (and <code class="computeroutput"><span class="keyword">constexpr</span></code>)</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.implementation_checks">Implementation
- Checks</a></span></dt>
- <dt><span class="section"><a href="advanced.html#boost_contract.advanced.old_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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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_idm45394999679376.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_idm45394998885120.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_idm45394998912688.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_idm45394998912688.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_idm45394998912688.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_idm45394998912688.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_idm45394999333872.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_idm45394998885120.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_idm45394998885120.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_idm45394998885120.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__idm45394999179040.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__idm45394999245856.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__idm45394999207792.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_idm45394998968720.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_idm45394998912688.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_idm45394998912688.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>
|