1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Better Error Detection</title> 5<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../index.html" title="Chapter 1. Boost.Convert 2.0"> 8<link rel="up" href="../index.html" title="Chapter 1. Boost.Convert 2.0"> 9<link rel="prev" href="getting_started/basic_conversion_failure_detection.html" title="Basic Conversion-Failure Detection"> 10<link rel="next" href="default_converter.html" title="Default Converter"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="getting_started/basic_conversion_failure_detection.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="default_converter.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h2 class="title" style="clear: both"> 27<a name="boost_convert.error_detection"></a><a class="link" href="error_detection.html" title="Better Error Detection">Better Error Detection</a> 28</h2></div></div></div> 29<div class="blockquote"><blockquote class="blockquote"><p> 30 <span class="bold"><strong><span class="emphasis"><em>"Detection is, or ought to be, an exact 31 science, ..." Sir Arthur Conan Doyle</em></span></strong></span> 32 </p></blockquote></div> 33<p> 34</p> 35<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i2</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"not an int"</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value_or</span><span class="special">(-</span><span class="number">1</span><span class="special">);</span> <span class="comment">// after the call i2==-1</span> 36 37<span class="keyword">if</span> <span class="special">(</span><span class="identifier">i2</span> <span class="special">==</span> <span class="special">-</span><span class="number">1</span><span class="special">)</span> <span class="identifier">process_failure</span><span class="special">();</span> 38</pre> 39<p> 40 </p> 41<p> 42 The code above is straightforward and self-explanatory but, strictly speaking, 43 is not entirely correct as -1 might be the result of a conversion failure or 44 the successful conversion of the "-1" string. Still, in reality "spare" 45 values (outside the valid/sensible range) are often available to indicate conversion 46 failures. If so, such straightorward deployment might be adequate. Alternatively, 47 it might be not that uncommon to ignore conversion failures altogether and 48 to simply log the event and to proceed with the supplied fallback value. 49 </p> 50<p> 51 Applications outside these mentioned categories still require conversion failure 52 reliably detected and processed accordingly. The <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span></code>'s 53 (only) answer is to throw on failure and <span class="emphasis"><em>Boost.Convert</em></span> 54 supports that behavior as well: 55 </p> 56<p> 57</p> 58<pre class="programlisting"><span class="keyword">try</span> 59<span class="special">{</span> 60 <span class="keyword">int</span> <span class="identifier">i1</span> <span class="special">=</span> <span class="identifier">lexical_cast</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str</span><span class="special">);</span> <span class="comment">// Throws if the conversion fails.</span> 61 <span class="keyword">int</span> <span class="identifier">i2</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value</span><span class="special">();</span> <span class="comment">// Throws if the conversion fails.</span> 62<span class="special">}</span> 63<span class="keyword">catch</span> <span class="special">(...)</span> 64<span class="special">{</span> 65 <span class="identifier">process_failure</span><span class="special">();</span> 66<span class="special">}</span> 67</pre> 68<p> 69 </p> 70<p> 71 However, to cater for a wider range of program-flow variations, <span class="emphasis"><em>Boost.Convert</em></span> 72 adds the flexibility of 73 </p> 74<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 75<li class="listitem"> 76 delaying the moment when the conversion-failure exception is actually thrown 77 or 78 </li> 79<li class="listitem"> 80 avoiding the exception altogether. 81 </li> 82</ul></div> 83<p> 84</p> 85<pre class="programlisting"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">r1</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str1</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">);</span> <span class="comment">// Does not throw on conversion failure.</span> 86<span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">r2</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str2</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">);</span> <span class="comment">// Does not throw on conversion failure.</span> 87<span class="comment">// ...</span> 88<span class="keyword">try</span> <span class="comment">// Delayed processing of potential exceptions.</span> 89<span class="special">{</span> 90 <span class="keyword">int</span> <span class="identifier">i1</span> <span class="special">=</span> <span class="identifier">r1</span><span class="special">.</span><span class="identifier">value</span><span class="special">();</span> <span class="comment">// Will throw if conversion failed.</span> 91 <span class="keyword">int</span> <span class="identifier">i2</span> <span class="special">=</span> <span class="identifier">r2</span><span class="special">.</span><span class="identifier">value</span><span class="special">();</span> <span class="comment">// Will throw if conversion failed.</span> 92<span class="special">}</span> 93<span class="keyword">catch</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bad_optional_access</span> <span class="keyword">const</span><span class="special">&)</span> 94<span class="special">{</span> 95 <span class="comment">// Handle failed conversion.</span> 96<span class="special">}</span> 97 98<span class="comment">// Exceptions are avoided altogether.</span> 99<span class="keyword">int</span> <span class="identifier">i1</span> <span class="special">=</span> <span class="identifier">r1</span> <span class="special">?</span> <span class="identifier">r1</span><span class="special">.</span><span class="identifier">value</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">fallback_value</span><span class="special">;</span> 100<span class="keyword">int</span> <span class="identifier">i2</span> <span class="special">=</span> <span class="identifier">r2</span><span class="special">.</span><span class="identifier">value_or</span><span class="special">(</span><span class="identifier">fallback_value</span><span class="special">);</span> 101<span class="keyword">int</span> <span class="identifier">i3</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str3</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value_or</span><span class="special">(</span><span class="identifier">fallback_value</span><span class="special">);</span> 102<span class="keyword">int</span> <span class="identifier">i4</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str3</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value_or_eval</span><span class="special">(</span><span class="identifier">fallback_function</span><span class="special">);</span> 103</pre> 104<p> 105 </p> 106<p> 107 Here <a href="../../../../../libs/optional/index.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span></code></a> 108 steps forward as the actual type returned by <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">convert</span><span class="special">()</span></code> which until now we avoided by immediately 109 calling its value-accessor methods: 110 </p> 111<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i1</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str1</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value</span><span class="special">();</span> 112<span class="keyword">int</span> <span class="identifier">i2</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str2</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value_or</span><span class="special">(</span><span class="identifier">fallback_value</span><span class="special">);</span> 113<span class="keyword">int</span> <span class="identifier">i3</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str3</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value_or_eval</span><span class="special">(</span><span class="identifier">fallback_function</span><span class="special">);</span> 114</pre> 115<div class="note"><table border="0" summary="Note"> 116<tr> 117<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> 118<th align="left">Note</th> 119</tr> 120<tr><td align="left" valign="top"><p> 121 One notable advantage of <code class="computeroutput"><span class="identifier">value_or_eval</span><span class="special">()</span></code> over <code class="computeroutput"><span class="identifier">value_or</span><span class="special">()</span></code> is that the actual calculation of the 122 <code class="computeroutput"><span class="identifier">fallback_value</span></code> is potentially 123 delayed and conditional on the success or failure of the conversion. 124 </p></td></tr> 125</table></div> 126<p> 127 From the user perspective, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">lexical_cast</span></code> 128 processes failure in a somewhat one-dimensional non-negotiable manner. <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">convert</span></code> 129 takes a more flexible approach. It provides choice and leaves the decision 130 to the user. It is not unimaginable that, on the library level, propagating 131 the conversion-failure exception might be the only available option. On the 132 application level though, in my personal experience, the choice has overwhelmingly 133 been to handle conversion failures <span class="emphasis"><em>locally</em></span>, i.e. avoiding 134 conversion-failure exception propagation or, better still, avoiding exceptions 135 altogether with program flows similar to: 136 </p> 137<p> 138</p> 139<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">res</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">);</span> 140 141<span class="keyword">if</span> <span class="special">(!</span><span class="identifier">res</span><span class="special">)</span> <span class="identifier">log</span><span class="special">(</span><span class="string">"str conversion failed!"</span><span class="special">);</span> 142 143<span class="keyword">int</span> <span class="identifier">i1</span> <span class="special">=</span> <span class="identifier">res</span><span class="special">.</span><span class="identifier">value_or</span><span class="special">(</span><span class="identifier">fallback_value</span><span class="special">);</span> 144 145<span class="comment">// ...proceed</span> 146</pre> 147<p> 148 </p> 149<p> 150 and 151 </p> 152<p> 153</p> 154<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">fallback_func</span> 155<span class="special">{</span> 156 <span class="keyword">int</span> <span class="keyword">operator</span><span class="special">()()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="identifier">log</span><span class="special">(</span><span class="string">"Failed to convert"</span><span class="special">);</span> <span class="keyword">return</span> <span class="number">42</span><span class="special">;</span> <span class="special">}</span> 157<span class="special">};</span> 158</pre> 159<p> 160 </p> 161<p> 162</p> 163<pre class="programlisting"><span class="comment">// Fallback function is called when failed</span> 164<span class="keyword">int</span> <span class="identifier">i2</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">).</span><span class="identifier">value_or_eval</span><span class="special">(</span><span class="identifier">fallback_func</span><span class="special">());</span> 165<span class="keyword">int</span> <span class="identifier">i3</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">str</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="identifier">fallback_func</span><span class="special">());</span> <span class="comment">// Same as above. Alternative API.</span> 166</pre> 167<p> 168 </p> 169</div> 170<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 171<td align="left"></td> 172<td align="right"><div class="copyright-footer">Copyright © 2009-2016 Vladimir Batov<p> 173 Distributed under the Boost Software License, Version 1.0. See copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>. 174 </p> 175</div></td> 176</tr></table> 177<hr> 178<div class="spirit-nav"> 179<a accesskey="p" href="getting_started/basic_conversion_failure_detection.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="default_converter.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> 180</div> 181</body> 182</html> 183