| 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
|---|
| 2 | |
|---|
| 3 | <html> |
|---|
| 4 | <head> |
|---|
| 5 | <meta http-equiv="Content-Language" content="en-us"> |
|---|
| 6 | <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> |
|---|
| 7 | |
|---|
| 8 | <title>The Boost Format library</title> |
|---|
| 9 | </head> |
|---|
| 10 | |
|---|
| 11 | <body bgcolor="white" text="black"> |
|---|
| 12 | <h1><img align="middle" alt="boost.png (6897 bytes)" height="86" src= |
|---|
| 13 | "../../../boost.png" width="277">The Boost Format library</h1> |
|---|
| 14 | |
|---|
| 15 | <p>The <code><a href= |
|---|
| 16 | "../../../boost/format.hpp"><boost/format.hpp></a></code> format |
|---|
| 17 | class provides printf-like formatting, in a type-safe manner which allows |
|---|
| 18 | output of user-defined types.<br></p> |
|---|
| 19 | |
|---|
| 20 | <ul> |
|---|
| 21 | <li><a href="#synopsis">Synopsis</a></li> |
|---|
| 22 | |
|---|
| 23 | <li><a href="#how_it_works">How it works</a></li> |
|---|
| 24 | |
|---|
| 25 | <li><a href="#examples">Examples</a></li> |
|---|
| 26 | |
|---|
| 27 | <li> |
|---|
| 28 | <a href="#syntax">Syntax</a> |
|---|
| 29 | |
|---|
| 30 | <ul> |
|---|
| 31 | <li><a href="#printf_directives">printf format-specification |
|---|
| 32 | syntax</a></li> |
|---|
| 33 | |
|---|
| 34 | <li><a href="#printf_differences">Incompatibilities with |
|---|
| 35 | printf</a></li> |
|---|
| 36 | </ul> |
|---|
| 37 | </li> |
|---|
| 38 | |
|---|
| 39 | <li><a href="#manipulators">Manipulators and the internal stream |
|---|
| 40 | state</a></li> |
|---|
| 41 | |
|---|
| 42 | <li><a href="#user-defined">User-defined types</a></li> |
|---|
| 43 | |
|---|
| 44 | <li><a href="#alternatives">Alternatives</a></li> |
|---|
| 45 | |
|---|
| 46 | <li><a href="#exceptions">Exceptions</a></li> |
|---|
| 47 | |
|---|
| 48 | <li><a href="#performance">Performance</a></li> |
|---|
| 49 | |
|---|
| 50 | <li><a href="#extract">Class Interface Extract</a></li> |
|---|
| 51 | |
|---|
| 52 | <li><a href="#rationale">Rationale</a></li> |
|---|
| 53 | </ul><a name="synopsis" id="synopsis"></a> |
|---|
| 54 | <hr> |
|---|
| 55 | |
|---|
| 56 | <h2>Synopsis</h2> |
|---|
| 57 | |
|---|
| 58 | <p>A format object is constructed from a format-string, and is then given |
|---|
| 59 | arguments through repeated calls to <i>operator%</i>.<br> |
|---|
| 60 | Each of those arguments are then converted to strings, who are in turn |
|---|
| 61 | combined into one string, according to the format-string.</p> |
|---|
| 62 | |
|---|
| 63 | <blockquote> |
|---|
| 64 | <pre> |
|---|
| 65 | cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50; |
|---|
| 66 | // prints "writing toto, x=40.230 : 50-th try" |
|---|
| 67 | </pre> |
|---|
| 68 | </blockquote><a name="how_it_works" id="how_it_works"></a> |
|---|
| 69 | <hr> |
|---|
| 70 | |
|---|
| 71 | <h2>How it works</h2> |
|---|
| 72 | |
|---|
| 73 | <ol> |
|---|
| 74 | <li>When you call <i>format(s)</i>, where s is the format-string, it |
|---|
| 75 | constructs an object, which parses the format string and look for all |
|---|
| 76 | directives in it and prepares internal structures for the next step.</li> |
|---|
| 77 | |
|---|
| 78 | <li>Then, either immediately, as in |
|---|
| 79 | |
|---|
| 80 | <blockquote> |
|---|
| 81 | <pre> |
|---|
| 82 | cout << format("%2% %1%") % 36 % 77 ) |
|---|
| 83 | </pre> |
|---|
| 84 | </blockquote>or later on, as in |
|---|
| 85 | |
|---|
| 86 | <blockquote> |
|---|
| 87 | <pre> |
|---|
| 88 | format fmter("%2% %1%"); |
|---|
| 89 | fmter % 36; fmter % 77; |
|---|
| 90 | </pre> |
|---|
| 91 | </blockquote>you <i>feed</i> variables into the formatter.<br> |
|---|
| 92 | those variables are dumped into an internal stream, which state is set |
|---|
| 93 | according to the given formatting options in the format-string -if |
|---|
| 94 | there are any-, and the format object stores the string results for the |
|---|
| 95 | last step. |
|---|
| 96 | </li> |
|---|
| 97 | |
|---|
| 98 | <li>Once all arguments have been fed you can dump the format object to a |
|---|
| 99 | stream, or get its string value by using the <i>str()</i> member |
|---|
| 100 | function, or the free function <i>str(const format& )</i> in |
|---|
| 101 | namespace <i>boost</i>. The result string stays accessible in the format |
|---|
| 102 | object until another argument is passed, at which time it is |
|---|
| 103 | reinitialised. |
|---|
| 104 | |
|---|
| 105 | <blockquote> |
|---|
| 106 | <pre> |
|---|
| 107 | |
|---|
| 108 | // fmter was previously created and fed arguments, it can print the result : |
|---|
| 109 | cout << fmter ; |
|---|
| 110 | |
|---|
| 111 | // You can take the string result : |
|---|
| 112 | string s = fmter.str(); |
|---|
| 113 | |
|---|
| 114 | // possibly several times : |
|---|
| 115 | s = fmter.str( ); |
|---|
| 116 | |
|---|
| 117 | // You can also do all steps at once : |
|---|
| 118 | cout << boost::format("%2% %1%") % 36 % 77; |
|---|
| 119 | |
|---|
| 120 | // using the str free function : |
|---|
| 121 | string s2 = str( format("%2% %1%") % 36 % 77 ); |
|---|
| 122 | |
|---|
| 123 | </pre> |
|---|
| 124 | </blockquote> |
|---|
| 125 | </li> |
|---|
| 126 | |
|---|
| 127 | <li>Optionnally, after step 3, you can re-use a format object and restart |
|---|
| 128 | at step2 : <i>fmter % 18 % 39;</i><br> |
|---|
| 129 | to format new variables with the same format-string, saving the expensive |
|---|
| 130 | processing involved at step 1.</li> |
|---|
| 131 | </ol>All in all, the format class translates a format-string (with |
|---|
| 132 | eventually printf-like directives) into operations on an internal stream, |
|---|
| 133 | and finally returns the result of the formatting, as a string, or directly |
|---|
| 134 | into an output stream. <a name="examples" id="examples"></a> |
|---|
| 135 | <hr> |
|---|
| 136 | |
|---|
| 137 | <h2>Examples</h2> |
|---|
| 138 | |
|---|
| 139 | <blockquote> |
|---|
| 140 | <pre> |
|---|
| 141 | using namespace std; |
|---|
| 142 | using boost::format; |
|---|
| 143 | using boost::io::group; |
|---|
| 144 | </pre> |
|---|
| 145 | </blockquote> |
|---|
| 146 | |
|---|
| 147 | <ul> |
|---|
| 148 | <li>Simple output, with reordering : |
|---|
| 149 | |
|---|
| 150 | <blockquote> |
|---|
| 151 | <pre> |
|---|
| 152 | |
|---|
| 153 | cout << format("%1% %2% %3% %2% %1% \n") % "11" % "22" % "333"; // 'simple' style. |
|---|
| 154 | |
|---|
| 155 | </pre> |
|---|
| 156 | </blockquote>It prints : "11 22 333 22 11 \n" |
|---|
| 157 | </li> |
|---|
| 158 | |
|---|
| 159 | <li>More precise formatting, with Posix-printf positional directives : |
|---|
| 160 | |
|---|
| 161 | <blockquote> |
|---|
| 162 | <pre> |
|---|
| 163 | |
|---|
| 164 | cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35; // Posix-Printf style |
|---|
| 165 | |
|---|
| 166 | </pre> |
|---|
| 167 | </blockquote>It prints : "(x,y) = ( -23, +35) \n" |
|---|
| 168 | </li> |
|---|
| 169 | |
|---|
| 170 | <li>classical printf directive, no reordering : |
|---|
| 171 | |
|---|
| 172 | <blockquote> |
|---|
| 173 | <pre> |
|---|
| 174 | |
|---|
| 175 | cout << format("writing %s, x=%s : %d-th step \n") % "toto" % 40.23 % 50; |
|---|
| 176 | |
|---|
| 177 | </pre> |
|---|
| 178 | </blockquote>It prints : "writing toto, x=40.23 : 50-th step \n" |
|---|
| 179 | </li> |
|---|
| 180 | |
|---|
| 181 | <li>Several ways to express the same thing : |
|---|
| 182 | |
|---|
| 183 | <blockquote> |
|---|
| 184 | <pre> |
|---|
| 185 | |
|---|
| 186 | cout << format("(x,y) = (%+5d,%+5d) \n") % -23 % 35; |
|---|
| 187 | cout << format("(x,y) = (%|+5|,%|+5|) \n") % -23 % 35; |
|---|
| 188 | |
|---|
| 189 | cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35; |
|---|
| 190 | cout << format("(x,y) = (%|1$+5|,%|2$+5|) \n") % -23 % 35; |
|---|
| 191 | |
|---|
| 192 | </pre> |
|---|
| 193 | </blockquote>all those print : "(x,y) = ( -23, +35) \n" |
|---|
| 194 | </li> |
|---|
| 195 | |
|---|
| 196 | <li>Using manipulators to modify the format-string : |
|---|
| 197 | |
|---|
| 198 | <blockquote> |
|---|
| 199 | <pre> |
|---|
| 200 | |
|---|
| 201 | format fmter("_%1$+5d_ %1$d \n"); |
|---|
| 202 | |
|---|
| 203 | format fmter2("_%1%_ %1% \n"); |
|---|
| 204 | fmter2.modify_item(1, group(showpos, setw(5)) ); |
|---|
| 205 | |
|---|
| 206 | cout << fmter % 101 ; |
|---|
| 207 | cout << fmter2 % 101 ; |
|---|
| 208 | |
|---|
| 209 | </pre> |
|---|
| 210 | </blockquote>Both print the same : "_ +101_ 101 \n" |
|---|
| 211 | </li> |
|---|
| 212 | |
|---|
| 213 | <li>Using manipulators with arguments : |
|---|
| 214 | |
|---|
| 215 | <blockquote> |
|---|
| 216 | <pre> |
|---|
| 217 | |
|---|
| 218 | cout << format("_%1%_ %1% \n") % group(showpos, setw(5), 101); |
|---|
| 219 | |
|---|
| 220 | </pre> |
|---|
| 221 | </blockquote>The manipulators are applied at each occurence of %1%, and |
|---|
| 222 | thus it prints : "_ +101_ +101 \n" |
|---|
| 223 | </li> |
|---|
| 224 | |
|---|
| 225 | <li>New formatting feature : 'absolute tabulations', useful inside loops, |
|---|
| 226 | to insure a field is printed at the same position from one line to the |
|---|
| 227 | next, even if the widthes of the previous arguments can vary a lot. |
|---|
| 228 | |
|---|
| 229 | <blockquote> |
|---|
| 230 | <pre> |
|---|
| 231 | |
|---|
| 232 | for(unsigned int i=0; i < names.size(); ++i) |
|---|
| 233 | cout << format("%1%, %2%, %|40t|%3%\n") % names[i] % surname[i] % tel[i]; |
|---|
| 234 | |
|---|
| 235 | </pre> |
|---|
| 236 | </blockquote>For some std::vector <i>names</i>, <i>surnames</i>, and |
|---|
| 237 | <i>tel</i> (see sample_new_features.cpp) it prints : |
|---|
| 238 | |
|---|
| 239 | <blockquote> |
|---|
| 240 | <pre> |
|---|
| 241 | Marc-François Michel, Durand, +33 (0) 123 456 789 |
|---|
| 242 | Jean, de Lattre de Tassigny, +33 (0) 987 654 321 |
|---|
| 243 | </pre> |
|---|
| 244 | </blockquote> |
|---|
| 245 | </li> |
|---|
| 246 | </ul> |
|---|
| 247 | <hr> |
|---|
| 248 | |
|---|
| 249 | <h2>Sample Files</h2> |
|---|
| 250 | |
|---|
| 251 | <p>The program <a href= |
|---|
| 252 | "../example/sample_formats.cpp">sample_formats.cpp</a> demonstrates simple |
|---|
| 253 | uses of <b>format</b>.<br></p> |
|---|
| 254 | |
|---|
| 255 | <p><a href="../example/sample_new_features.cpp">sample_new_features.cpp</a> |
|---|
| 256 | illustrates the few formatting features that were added to printf's syntax |
|---|
| 257 | such as simple positional directives, centered alignment, and |
|---|
| 258 | 'tabulations'.<br></p> |
|---|
| 259 | |
|---|
| 260 | <p><a href="../example/sample_advanced.cpp">sample_advanced.cpp</a> |
|---|
| 261 | demonstrates uses of advanced features, like reusing, and modifying, format |
|---|
| 262 | objects, etc..<br></p> |
|---|
| 263 | |
|---|
| 264 | <p>And <a href="../example/sample_userType.cpp">sample_userType.cpp</a> |
|---|
| 265 | shows the behaviour of the <b>format</b> library on user-defined |
|---|
| 266 | types.</p><a name="syntax" id="syntax"></a> |
|---|
| 267 | <hr> |
|---|
| 268 | |
|---|
| 269 | <h2>Syntax</h2> |
|---|
| 270 | |
|---|
| 271 | <p><b>boost::format(</b> format-string <b>) %</b> arg1 <b>%</b> arg2 |
|---|
| 272 | <b>%</b> ... <b>%</b> argN</p> |
|---|
| 273 | |
|---|
| 274 | <p>The <i>format-string</i> contains text in which special directives will |
|---|
| 275 | be replaced by strings resulting from the formatting of the given |
|---|
| 276 | arguments.<br> |
|---|
| 277 | The legacy syntax in the C and C++ worlds is the one used by printf, and |
|---|
| 278 | thus format can use directly printf format-strings, and produce the same |
|---|
| 279 | result (in almost all cases. see <a href= |
|---|
| 280 | "#printf_differences">Incompatibilities with printf</a> for details)<br> |
|---|
| 281 | This core syntax was extended, to allow new features, but also to adapt to |
|---|
| 282 | the C++ streams context. Thus, format accepts several forms of directives |
|---|
| 283 | in format-strings :</p> |
|---|
| 284 | |
|---|
| 285 | <ul> |
|---|
| 286 | <li>Legacy printf format strings : <b>%</b><i>spec</i> where <i>spec</i> |
|---|
| 287 | is a <a href="#printf_directives">printf format specification</a><br> |
|---|
| 288 | <i>spec</i> passes formatting options, like width, alignment, numerical |
|---|
| 289 | base used for formatting numbers, as well as other specific flags. But |
|---|
| 290 | the classical <i>type-specification</i> flag of printf has a weaker |
|---|
| 291 | meaning in format. It merely sets the appropriate flags on the internal |
|---|
| 292 | stream, and/or formatting parameters, but does not require the |
|---|
| 293 | corresponding argument to be of a specific type.<br> |
|---|
| 294 | e.g. : the specification <i>2$x</i>, meaning "print argument number 2, |
|---|
| 295 | which is an integral number, in hexa" for printf, merely means "print |
|---|
| 296 | argument 2 with stream basefield flags set to <i>hex</i>" for |
|---|
| 297 | format.</li> |
|---|
| 298 | |
|---|
| 299 | <li><b>%|</b><i>spec</i><b>|</b> where <i>spec</i> is a printf format |
|---|
| 300 | specification.<br> |
|---|
| 301 | The brackets are introduced, to improve the readability of the |
|---|
| 302 | format-string, but primarily, to make the <i>type-conversion |
|---|
| 303 | character</i> optional in <i>spec</i>. This information is not necessary |
|---|
| 304 | with C++ variables, but with direct printf syntax, it is necessary to |
|---|
| 305 | always give a type-conversion character, merely because this character is |
|---|
| 306 | crucial to determine the end of a format-specification.<br> |
|---|
| 307 | e.g. : "%|-5|" will format the next variable with width set to 5, and |
|---|
| 308 | left-alignment just like the following printf directives : "%-5g", |
|---|
| 309 | "%-5f", "%-5s" ..</li> |
|---|
| 310 | |
|---|
| 311 | <li><b>%</b><i>N</i><b>%</b><br> |
|---|
| 312 | This simple positional notation requests the formatting of the |
|---|
| 313 | <i>N</i>-th argument - wihout any formatting option.<br> |
|---|
| 314 | (It's merely a shortcut to Printf's positional directives (like |
|---|
| 315 | "%<i>N</i>$s"), but a major benefit is that it's much more readable, and |
|---|
| 316 | does not use a "type-conversion" character)</li> |
|---|
| 317 | </ul>On top of the standard printf format specifications, new features were |
|---|
| 318 | implemented, like centered alignment. See <a href="#new_directives">new |
|---|
| 319 | format specification</a> for details. <a name="printf_directives" id= |
|---|
| 320 | "printf_directives"></a> |
|---|
| 321 | |
|---|
| 322 | <h3>printf format specifications</h3> |
|---|
| 323 | |
|---|
| 324 | <p>The printf format specifications supported by Boost.format follows the |
|---|
| 325 | Unix98 <a href= |
|---|
| 326 | "http://www.opengroup.org/onlinepubs/7908799/xsh/fprintf.html">Open-group |
|---|
| 327 | printf</a> precise syntax, rather than the standard C printf, which does |
|---|
| 328 | not support positional arguments. (Common flags have the same meaning in |
|---|
| 329 | both, so it should not be a headache for anybody)<br> |
|---|
| 330 | <i>Note that it is an error to use positional format specifications</i> |
|---|
| 331 | (e.g. <i>%3$+d</i>) <i>mixed with non-positional ones</i> (e.g. <i>%+d</i>) |
|---|
| 332 | <i>in the same format string.</i><br> |
|---|
| 333 | In the Open-group specification, referring to the same argument several |
|---|
| 334 | times (e.g. <i>"%1$d %1$d"</i>) has undefined behaviour. Boost.format's |
|---|
| 335 | behaviour in such cases is to allow each argument to be reffered to any |
|---|
| 336 | number of times. The only constraint is that it expects exactly <i>P</i> |
|---|
| 337 | arguments, <i>P</i> being the maximum argument number used in the format |
|---|
| 338 | string. (e.g., for "%1$d %10$d", <i>P</i> == 10 ).<br> |
|---|
| 339 | Supplying more, or less, than <i>P</i> arguments raises an exception. |
|---|
| 340 | (unless it was set otherwise, see <a href="#exceptions">exceptions</a>)</p> |
|---|
| 341 | |
|---|
| 342 | <p><br> |
|---|
| 343 | <br> |
|---|
| 344 | A specification <i>spec</i> has the form : [ <i>N</i><b>$</b> ] [ |
|---|
| 345 | <i>flags</i> ] [ <i>width</i> ] [ <b>.</b> <i>precision</i> ] |
|---|
| 346 | <i>type-char</i><br> |
|---|
| 347 | <br> |
|---|
| 348 | Fields insided square brackets are optional. Each of those fields are |
|---|
| 349 | explained one by one in the following list :</p> |
|---|
| 350 | |
|---|
| 351 | <ul> |
|---|
| 352 | <li><i>N</i> <b>$</b> (optional field) specifies that the format |
|---|
| 353 | specification applies to the <i>N</i>-th argument. (it is called a |
|---|
| 354 | <i>positional format specification</i>)<br> |
|---|
| 355 | If this is not present, arguments are taken one by one. (and it is then |
|---|
| 356 | an error to later supply an argument number)</li> |
|---|
| 357 | |
|---|
| 358 | <li> |
|---|
| 359 | <i>flags</i> is a sequences of any of those : |
|---|
| 360 | |
|---|
| 361 | <blockquote> |
|---|
| 362 | <table border="1" cellpadding="5" summary=""> |
|---|
| 363 | <tr> |
|---|
| 364 | <td><b>Flag</b></td> |
|---|
| 365 | |
|---|
| 366 | <td><b>Meaning</b></td> |
|---|
| 367 | |
|---|
| 368 | <td><b>effect on internal stream</b></td> |
|---|
| 369 | </tr> |
|---|
| 370 | |
|---|
| 371 | <tr> |
|---|
| 372 | <td><b>'-'</b></td> |
|---|
| 373 | |
|---|
| 374 | <td>left alignment</td> |
|---|
| 375 | |
|---|
| 376 | <td>N/A (applied later on the string)</td> |
|---|
| 377 | </tr> |
|---|
| 378 | |
|---|
| 379 | <tr> |
|---|
| 380 | <td><b>'='</b></td> |
|---|
| 381 | |
|---|
| 382 | <td>centered alignment</td> |
|---|
| 383 | |
|---|
| 384 | <td>N/A (applied later on the string)<br> |
|---|
| 385 | <i>- note : added feature, not in printf -</i></td> |
|---|
| 386 | </tr> |
|---|
| 387 | |
|---|
| 388 | <tr> |
|---|
| 389 | <td><b>'_'</b></td> |
|---|
| 390 | |
|---|
| 391 | <td>internal alignment</td> |
|---|
| 392 | |
|---|
| 393 | <td>sets internal alignment<br> |
|---|
| 394 | <i>- note : added feature, not in printf -</i></td> |
|---|
| 395 | </tr> |
|---|
| 396 | |
|---|
| 397 | <tr> |
|---|
| 398 | <td><b>'+'</b></td> |
|---|
| 399 | |
|---|
| 400 | <td>show sign even for positive numbers</td> |
|---|
| 401 | |
|---|
| 402 | <td>sets <i>showpos</i></td> |
|---|
| 403 | </tr> |
|---|
| 404 | |
|---|
| 405 | <tr> |
|---|
| 406 | <td><b>'#'</b></td> |
|---|
| 407 | |
|---|
| 408 | <td>show numerical base, and decimal point</td> |
|---|
| 409 | |
|---|
| 410 | <td>sets <i>showbase</i> and <i>showpoint</i></td> |
|---|
| 411 | </tr> |
|---|
| 412 | |
|---|
| 413 | <tr> |
|---|
| 414 | <td><b>'0'</b></td> |
|---|
| 415 | |
|---|
| 416 | <td>pad with 0's (inserted after sign or base indicator)</td> |
|---|
| 417 | |
|---|
| 418 | <td>if not left-aligned, calls <i>setfill('0')</i> and sets |
|---|
| 419 | <i>internal</i><br> |
|---|
| 420 | Extra actions are taken after stream conversion to handle |
|---|
| 421 | <a href="#user-defined">user-defined output</a>.</td> |
|---|
| 422 | </tr> |
|---|
| 423 | |
|---|
| 424 | <tr> |
|---|
| 425 | <td><b>' '</b></td> |
|---|
| 426 | |
|---|
| 427 | <td>if the string does not begin with <i>+</i> or <i>-</i>, |
|---|
| 428 | insert a <i>space</i> before the converted string</td> |
|---|
| 429 | |
|---|
| 430 | <td>N/A (applied later on the string)<br> |
|---|
| 431 | Different to printf's behaviour : it is not affected by internal |
|---|
| 432 | alignment</td> |
|---|
| 433 | </tr> |
|---|
| 434 | </table> |
|---|
| 435 | </blockquote> |
|---|
| 436 | </li> |
|---|
| 437 | |
|---|
| 438 | <li><i>width</i> specifies a minimal width for the string resulting form |
|---|
| 439 | the conversion. If necessary, the string will be padded with alignment |
|---|
| 440 | and fill characters either set on the stream via manipulators, or |
|---|
| 441 | specified by the format-string (e.g. flags '0', '-', ..)<br> |
|---|
| 442 | Note that width is not just set on the conversion stream. To support |
|---|
| 443 | output of <a href="#user-defined">user-defined types</a> (that might call |
|---|
| 444 | <i>operator<<</i> many times on several members), the width is |
|---|
| 445 | handled after stream conversion of the whole argument object, in the |
|---|
| 446 | format class code.</li> |
|---|
| 447 | |
|---|
| 448 | <li> |
|---|
| 449 | <i>precision</i> (preceded by a point), sets the stream's |
|---|
| 450 | <i>precision</i> |
|---|
| 451 | |
|---|
| 452 | <ul> |
|---|
| 453 | <li>When outputting a floatting type number, it sets the maximum |
|---|
| 454 | number of digits |
|---|
| 455 | |
|---|
| 456 | <ul> |
|---|
| 457 | <li>after decimal point when in fixed or scientific mode</li> |
|---|
| 458 | |
|---|
| 459 | <li>in total when in default mode ('<i>general mode</i>', like |
|---|
| 460 | <i>%g</i>)</li> |
|---|
| 461 | </ul> |
|---|
| 462 | </li> |
|---|
| 463 | |
|---|
| 464 | <li>When used with type-char <b>s</b> or <b>S</b> it takes another |
|---|
| 465 | meaning : the conversion string is truncated to the <i>precision</i> |
|---|
| 466 | first chars. (Note that the eventual padding to <i>width</i> is done |
|---|
| 467 | after truncation.)</li> |
|---|
| 468 | </ul> |
|---|
| 469 | </li> |
|---|
| 470 | |
|---|
| 471 | <li> |
|---|
| 472 | <i>type-char</i>. it does <b>not</b> impose the concerned argument to |
|---|
| 473 | be of a restricted set of types, but merely sets the flags that are |
|---|
| 474 | associated with this type specification. |
|---|
| 475 | |
|---|
| 476 | <blockquote> |
|---|
| 477 | <table border="1" cellpadding="5" summary=""> |
|---|
| 478 | <tr> |
|---|
| 479 | <td><b>Type-Char</b></td> |
|---|
| 480 | |
|---|
| 481 | <td><b>Meaning</b></td> |
|---|
| 482 | |
|---|
| 483 | <td><b>effect on stream</b></td> |
|---|
| 484 | </tr> |
|---|
| 485 | |
|---|
| 486 | <tr> |
|---|
| 487 | <td><b>p or x</b></td> |
|---|
| 488 | |
|---|
| 489 | <td>hexadecimal output</td> |
|---|
| 490 | |
|---|
| 491 | <td>sets <i>hex</i></td> |
|---|
| 492 | </tr> |
|---|
| 493 | |
|---|
| 494 | <tr> |
|---|
| 495 | <td><b>o</b></td> |
|---|
| 496 | |
|---|
| 497 | <td>octal output</td> |
|---|
| 498 | |
|---|
| 499 | <td>sets <i>oct</i></td> |
|---|
| 500 | </tr> |
|---|
| 501 | |
|---|
| 502 | <tr> |
|---|
| 503 | <td><b>e</b></td> |
|---|
| 504 | |
|---|
| 505 | <td>scientific float format</td> |
|---|
| 506 | |
|---|
| 507 | <td>sets floatfield bits to <i>scientific</i></td> |
|---|
| 508 | </tr> |
|---|
| 509 | |
|---|
| 510 | <tr> |
|---|
| 511 | <td><b>f</b></td> |
|---|
| 512 | |
|---|
| 513 | <td>fixed float format</td> |
|---|
| 514 | |
|---|
| 515 | <td>sets floatfield bits to <i>fixed</i></td> |
|---|
| 516 | </tr> |
|---|
| 517 | |
|---|
| 518 | <tr> |
|---|
| 519 | <td><b>g</b></td> |
|---|
| 520 | |
|---|
| 521 | <td>general -default- float format</td> |
|---|
| 522 | |
|---|
| 523 | <td><b>unset</b> all floatfield bits</td> |
|---|
| 524 | </tr> |
|---|
| 525 | |
|---|
| 526 | <tr> |
|---|
| 527 | <td><b>X, E</b> or <b>G</b></td> |
|---|
| 528 | |
|---|
| 529 | <td>same effect as their lowercase counterparts, but using |
|---|
| 530 | uppercase letters for number outputs. (exponents, hex digits, |
|---|
| 531 | ..)</td> |
|---|
| 532 | |
|---|
| 533 | <td>same effects as <i>'x'</i>, <i>'e'</i>, or <i>'g'</i>, |
|---|
| 534 | <b>plus</b> <i>uppercase</i></td> |
|---|
| 535 | </tr> |
|---|
| 536 | |
|---|
| 537 | <tr> |
|---|
| 538 | <td><b>d, i</b> or <b>u</b></td> |
|---|
| 539 | |
|---|
| 540 | <td><b>decimal</b> type output</td> |
|---|
| 541 | |
|---|
| 542 | <td>sets basefield bits to <i>dec</i></td> |
|---|
| 543 | </tr> |
|---|
| 544 | |
|---|
| 545 | <tr> |
|---|
| 546 | <td><b>s</b> or <b>S</b></td> |
|---|
| 547 | |
|---|
| 548 | <td>string output</td> |
|---|
| 549 | |
|---|
| 550 | <td><i>precision</i> specification is unset, and its value goes |
|---|
| 551 | to an internal field for later 'truncation'. (see |
|---|
| 552 | <i>precision</i> explanation above)</td> |
|---|
| 553 | </tr> |
|---|
| 554 | |
|---|
| 555 | <tr> |
|---|
| 556 | <td><b>c</b> or <b>C</b></td> |
|---|
| 557 | |
|---|
| 558 | <td>1-character output</td> |
|---|
| 559 | |
|---|
| 560 | <td>only the first character of the conversion string is |
|---|
| 561 | used.</td> |
|---|
| 562 | </tr> |
|---|
| 563 | |
|---|
| 564 | <tr> |
|---|
| 565 | <td><b>%</b></td> |
|---|
| 566 | |
|---|
| 567 | <td>print the character <i>%</i></td> |
|---|
| 568 | |
|---|
| 569 | <td>N/A</td> |
|---|
| 570 | </tr> |
|---|
| 571 | </table> |
|---|
| 572 | </blockquote> |
|---|
| 573 | |
|---|
| 574 | <p>Note that the 'n' type specification is ignored (and so is the |
|---|
| 575 | corresponding argument), because it does not fit in this context.<br> |
|---|
| 576 | Also, printf 'l', 'L', or 'h' modifiers (to indicate wide, long or |
|---|
| 577 | short types) are supported (and simply have no effect on the internal |
|---|
| 578 | stream).</p> |
|---|
| 579 | </li> |
|---|
| 580 | </ul><a name="new_directives" id="new_directives"></a> |
|---|
| 581 | |
|---|
| 582 | <h3>new format-specifications</h3> |
|---|
| 583 | |
|---|
| 584 | <ul> |
|---|
| 585 | <li>as stated in the flags table, centered and internal alignment flags |
|---|
| 586 | (' <i>=</i> ', and ' <i>_</i> ') were added.</li> |
|---|
| 587 | |
|---|
| 588 | <li><i><b>%{</b>n</i><b>t}</b> , where <i>n</i> is a positive number, |
|---|
| 589 | inserts an <i>absolute tabulation</i>. It means that format will, if |
|---|
| 590 | needed, fill the string with characters, until the length of the string |
|---|
| 591 | created so far reaches <i>n</i> characters. (see <a href= |
|---|
| 592 | "#examples">examples</a> )</li> |
|---|
| 593 | |
|---|
| 594 | <li><b>%{</b><i>n</i><b>T</b><i>X</i><b>}</b> inserts a tabulation in the |
|---|
| 595 | same way, but using <i>X</i> as fill character instead of the current |
|---|
| 596 | 'fill' char of the stream (which is <i>space</i> for a stream in default |
|---|
| 597 | state)</li> |
|---|
| 598 | </ul><a name="printf_differences" id="printf_differences"></a> |
|---|
| 599 | |
|---|
| 600 | <h2>Differences of behaviour vs printf</h2>Suppose you have variables |
|---|
| 601 | <i>x1, x2</i> (built_in types, supported by C's printf),<br> |
|---|
| 602 | and a format string <i>s</i> intended for use with a printf function this |
|---|
| 603 | way : |
|---|
| 604 | |
|---|
| 605 | <blockquote> |
|---|
| 606 | <pre> |
|---|
| 607 | printf(s, x1, x2); |
|---|
| 608 | </pre> |
|---|
| 609 | </blockquote><br> |
|---|
| 610 | In almost all cases, the result will be the same as with this command : |
|---|
| 611 | |
|---|
| 612 | <blockquote> |
|---|
| 613 | <pre> |
|---|
| 614 | cout << format(s) % x1 % x2; |
|---|
| 615 | </pre> |
|---|
| 616 | </blockquote> |
|---|
| 617 | |
|---|
| 618 | <p>But because some printf format specifications don't translate well into |
|---|
| 619 | stream formatting options, there are a few notable imperfections in the way |
|---|
| 620 | Boost.format emulates printf.<br> |
|---|
| 621 | In any case, the <i>format</i> class should quietly ignore the unsupported |
|---|
| 622 | options, so that printf format-strings are always accepted by format and |
|---|
| 623 | produce almost the same output as printf.</p><br> |
|---|
| 624 | Here is the full list of such differences : |
|---|
| 625 | |
|---|
| 626 | <ul> |
|---|
| 627 | <li><b>'0'</b> and <b>' '</b> options : printf ignores these options for |
|---|
| 628 | non numeric conversions, but format applies them to all types of |
|---|
| 629 | variables. (so it is possible to use those options on user-defined types, |
|---|
| 630 | e.g. a Rational class, etc..)</li> |
|---|
| 631 | |
|---|
| 632 | <li><b>precision</b> for integral types arguments has a special meaning |
|---|
| 633 | for printf :<br> |
|---|
| 634 | <i>printf( "(%5.3d)" , 7 ) ;</i> prints « ( 007) »<br> |
|---|
| 635 | While format, like streams, ignores the precision parameter for integral |
|---|
| 636 | types conversions.</li> |
|---|
| 637 | |
|---|
| 638 | <li>the <b>'</b> printf option (<i>format with thousands grouping |
|---|
| 639 | characters)</i>) has no effect in format.</li> |
|---|
| 640 | |
|---|
| 641 | <li>Width or precision set to asterisk (<i>*</i>) are used by printf to |
|---|
| 642 | read this field from an argument. e.g. |
|---|
| 643 | <i>printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);</i><br> |
|---|
| 644 | This class does not support this mechanism for now. so such precision or |
|---|
| 645 | width fields are quietly ignored by the parsing.</li> |
|---|
| 646 | </ul>Also, note that the special <b>'n'</b> type-specification (used to |
|---|
| 647 | tell printf to save in a variable the number of characters output by the |
|---|
| 648 | formatting) has no effect in format.<br> |
|---|
| 649 | Thus format strings containing this type-specification should produce the |
|---|
| 650 | same converted string by printf or format. It will not cause differences in |
|---|
| 651 | the formatted strings between printf and format.<br> |
|---|
| 652 | To get the number of characters in the formatted string using Boost.Format, |
|---|
| 653 | you can use the <i>size()</i> member function : |
|---|
| 654 | |
|---|
| 655 | <blockquote> |
|---|
| 656 | <pre> |
|---|
| 657 | format formatter("%+5d"); |
|---|
| 658 | cout << formatter % x; |
|---|
| 659 | unsigned int n = formatter.size(); |
|---|
| 660 | </pre> |
|---|
| 661 | </blockquote><a name="user-defined" id="user-defined"></a> |
|---|
| 662 | <hr> |
|---|
| 663 | |
|---|
| 664 | <h2>User-defined types output</h2> |
|---|
| 665 | |
|---|
| 666 | <p>All flags which are translated into modification to the stream state act |
|---|
| 667 | recursively within user-defined types. ( the flags remain active, and so |
|---|
| 668 | does the desired format option, for each of the '<<' operations that |
|---|
| 669 | might be called by the user-defined class)</p>e.g., with a Rational class, |
|---|
| 670 | we would have something like : |
|---|
| 671 | |
|---|
| 672 | <blockquote> |
|---|
| 673 | <pre> |
|---|
| 674 | Rational ratio(16,9); |
|---|
| 675 | cerr << format("%#x \n") % ratio; // -> "0x10/0x9 \n" |
|---|
| 676 | </pre> |
|---|
| 677 | </blockquote> |
|---|
| 678 | |
|---|
| 679 | <p>It's a different story for other formatting options. For example, |
|---|
| 680 | setting width applies to the final output produced by the object, not to |
|---|
| 681 | each of its internal outputs, and that's fortunate :</p> |
|---|
| 682 | |
|---|
| 683 | <blockquote> |
|---|
| 684 | <pre> |
|---|
| 685 | cerr << format("%-8d") % ratio; // -> "16/9 " and not "16 /9 " |
|---|
| 686 | cerr << format("%=8d") % ratio; // -> " 16/9 " and not " 16 / 9 " |
|---|
| 687 | </pre> |
|---|
| 688 | </blockquote> |
|---|
| 689 | |
|---|
| 690 | <p><br> |
|---|
| 691 | But so does the 0 and ' ' options (contrarily to '+' which is directly |
|---|
| 692 | translated to the stream state by <i>showpos</i>. But no such flags exist |
|---|
| 693 | for the zero and space printf options)<br> |
|---|
| 694 | and that is less natural :</p> |
|---|
| 695 | |
|---|
| 696 | <blockquote> |
|---|
| 697 | <pre> |
|---|
| 698 | cerr << format("%+08d \n") % ratio; // -> "+00016/9" |
|---|
| 699 | cerr << format("% 08d \n") % ratio; // -> "000 16/9" |
|---|
| 700 | </pre> |
|---|
| 701 | </blockquote>It is possible to obtain a better behaviour by carefully |
|---|
| 702 | designing the Rational's <i>operator<<</i> to handle the stream's |
|---|
| 703 | width, alignment and <i>showpos</i> paramaters by itself. This is |
|---|
| 704 | demonstrated in <a href= |
|---|
| 705 | "../example/sample_userType.cpp">sample_userType.cpp</a>. <a name= |
|---|
| 706 | "manipulators" id="manipulators"></a> |
|---|
| 707 | <hr> |
|---|
| 708 | |
|---|
| 709 | <h3>Manipulators, and internal stream state</h3> |
|---|
| 710 | |
|---|
| 711 | <p>The internal stream state of <b>format</b> is saved before and restored |
|---|
| 712 | after output of an argument; therefore, the modifiers are not sticky and |
|---|
| 713 | affect only the argument they are applied to.<br> |
|---|
| 714 | The default state for streams, as stated by the standard, is : precision 6, |
|---|
| 715 | width 0, right alignment, and decimal flag set.</p> |
|---|
| 716 | |
|---|
| 717 | <p>The state of the internal <b>format</b> stream can be changed by |
|---|
| 718 | manipulators passed along with the argument; via the <i>group</i> function, |
|---|
| 719 | like that :</p> |
|---|
| 720 | |
|---|
| 721 | <blockquote> |
|---|
| 722 | <pre> |
|---|
| 723 | cout << format("%1% %2% %1%\n") % group(hex, showbase, 40) % 50; // prints "0x28 50 0x28\n" |
|---|
| 724 | </pre> |
|---|
| 725 | </blockquote> |
|---|
| 726 | |
|---|
| 727 | <p><br> |
|---|
| 728 | When passing N items inside a 'group' Boost.format needs to process |
|---|
| 729 | manipulators diferently from regular argument, and thus using group is |
|---|
| 730 | subject to the following constraints :</p> |
|---|
| 731 | |
|---|
| 732 | <ol> |
|---|
| 733 | <li>the object to be printed must be passed as the last item in the |
|---|
| 734 | group</li> |
|---|
| 735 | |
|---|
| 736 | <li>the first N-1 items are treated as manipulators, and if they do |
|---|
| 737 | produce output, it is discarded</li> |
|---|
| 738 | </ol> |
|---|
| 739 | |
|---|
| 740 | <p>Such manipulators are passed to the streams right before the following |
|---|
| 741 | argument, at every occurence. Note that formatting options specified within |
|---|
| 742 | the format string are overridden by stream state modifiers passed this way. |
|---|
| 743 | For instance in the following code, the <i>hex</i> manipulator has priority |
|---|
| 744 | over the <i>d</i> type-specification in the format-string which would set |
|---|
| 745 | decimal output :</p> |
|---|
| 746 | |
|---|
| 747 | <blockquote> |
|---|
| 748 | <pre> |
|---|
| 749 | cout << format("%1$d %2% %1%\n") % group(hex, showbase, 40) % 50; |
|---|
| 750 | // prints "0x28 50 0x28\n" |
|---|
| 751 | </pre> |
|---|
| 752 | </blockquote><a name="alternatives" id="alternatives"></a> |
|---|
| 753 | |
|---|
| 754 | <h2>Alternatives</h2> |
|---|
| 755 | |
|---|
| 756 | <ul> |
|---|
| 757 | <li><b>printf</b> is the classical alternative, that is not type safe and |
|---|
| 758 | not extendable to user-defined types.</li> |
|---|
| 759 | |
|---|
| 760 | <li>ofrstream.cc by Karl Nelson's design was a big source of inspiration |
|---|
| 761 | to this format class.</li> |
|---|
| 762 | |
|---|
| 763 | <li>James Kanze's library has a format class (in |
|---|
| 764 | <i>srcode/Extended/format</i> ) which looks very well polished. Its |
|---|
| 765 | design has in common with this class the use of internal stream for the |
|---|
| 766 | actual conversions, as well as using operators to pass arguments. (but |
|---|
| 767 | his class, as ofrstream, uses <i>operator<<</i> rather <i>than |
|---|
| 768 | operator%</i> )</li> |
|---|
| 769 | |
|---|
| 770 | <li><a href="http://groups.yahoo.com/group/boost/files/format3/">Karl |
|---|
| 771 | Nelson's library</a> was intented as demonstration of alternative |
|---|
| 772 | solutions in discussions on Boost's list for the design of |
|---|
| 773 | Boost.format.</li> |
|---|
| 774 | </ul><a name="exceptions" id="exceptions"></a> |
|---|
| 775 | <hr> |
|---|
| 776 | |
|---|
| 777 | <h2>Exceptions</h2> |
|---|
| 778 | |
|---|
| 779 | <p>Boost.format enforces a number of rules on the usage of format objects. |
|---|
| 780 | The format-string must obeys the syntax described above, the user must |
|---|
| 781 | supply exactly the right number of arguments before outputting to the final |
|---|
| 782 | destination, and if using modify_item or bind_arg, items and arguments |
|---|
| 783 | index must not be out of range.<br> |
|---|
| 784 | When format detects that one of these rules is not satisfied, it raises a |
|---|
| 785 | corresponding exception, so that the mistakes don't go unnoticed and |
|---|
| 786 | unhandled.<br> |
|---|
| 787 | But the user can change this behaviour to fit his needs, and select which |
|---|
| 788 | types of errors may raise exceptions using the following functions :</p> |
|---|
| 789 | |
|---|
| 790 | <blockquote> |
|---|
| 791 | <pre> |
|---|
| 792 | |
|---|
| 793 | unsigned char exceptions(unsigned char newexcept); // query and set |
|---|
| 794 | unsigned char exceptions() const; // just query |
|---|
| 795 | |
|---|
| 796 | </pre> |
|---|
| 797 | </blockquote> |
|---|
| 798 | |
|---|
| 799 | <p>The user can compute the argument <i>newexcept</i> by combining the |
|---|
| 800 | following atoms using binary arithmetic :</p> |
|---|
| 801 | |
|---|
| 802 | <ul> |
|---|
| 803 | <li><b>boost::io::bad_format_string_bit</b> selects errors due to |
|---|
| 804 | ill-formed format-strings.</li> |
|---|
| 805 | |
|---|
| 806 | <li><b>boost::io::too_few_args_bit</b> selects errors due to asking for |
|---|
| 807 | the srting result before all arguments are passed.</li> |
|---|
| 808 | |
|---|
| 809 | <li><b>boost::io::too_many_args_bit</b> selects errors due to passing too |
|---|
| 810 | many arguments.</li> |
|---|
| 811 | |
|---|
| 812 | <li><b>boost::io::out_of_range_bit</b> select errors due to out of range |
|---|
| 813 | index supplied by the user when calling <i>modify_item</i> or other |
|---|
| 814 | functions taking an item index (or an argument index)</li> |
|---|
| 815 | |
|---|
| 816 | <li><b>boost::io::all_error_bits</b> selects all errors</li> |
|---|
| 817 | |
|---|
| 818 | <li><b>boost::io::no_error_bits</b> selects no error.</li> |
|---|
| 819 | </ul> |
|---|
| 820 | |
|---|
| 821 | <p>For instance, if you don't want Boost.format to detect bad number of |
|---|
| 822 | arguments, you can define a specific wrapper function for building format |
|---|
| 823 | objects with the right exceptions settings :</p> |
|---|
| 824 | |
|---|
| 825 | <blockquote> |
|---|
| 826 | <pre> |
|---|
| 827 | |
|---|
| 828 | boost::format my_fmt(const std::string & f_string) { |
|---|
| 829 | using namespace boost::io; |
|---|
| 830 | format fmter(f_string); |
|---|
| 831 | fmter.exceptions( all_error_bits ^ ( too_many_args_bit | too_few_args_bit ) ); |
|---|
| 832 | return fmter; |
|---|
| 833 | } |
|---|
| 834 | |
|---|
| 835 | </pre> |
|---|
| 836 | </blockquote>It is then allowed to give more arguments than needed (they |
|---|
| 837 | are simply ignored) : |
|---|
| 838 | |
|---|
| 839 | <blockquote> |
|---|
| 840 | <pre> |
|---|
| 841 | |
|---|
| 842 | cout << my_fmt(" %1% %2% \n") % 1 % 2 % 3 % 4 % 5; |
|---|
| 843 | |
|---|
| 844 | </pre> |
|---|
| 845 | </blockquote>And if we ask for the result before all arguments are |
|---|
| 846 | supplied, the corresponding part of the result is simply empty |
|---|
| 847 | |
|---|
| 848 | <blockquote> |
|---|
| 849 | <pre> |
|---|
| 850 | |
|---|
| 851 | cout << my_fmt(" _%2%_ _%1%_ \n") % 1 ; |
|---|
| 852 | // prints " __ _1_ \n" |
|---|
| 853 | |
|---|
| 854 | </pre> |
|---|
| 855 | </blockquote><a name="performance" id="performance"></a> |
|---|
| 856 | <hr> |
|---|
| 857 | |
|---|
| 858 | <h2>A Note about performance</h2> |
|---|
| 859 | |
|---|
| 860 | <p>The performance of boost::format for formatting a few builtin type |
|---|
| 861 | arguments with reordering can be compared to that of Posix-printf, and of |
|---|
| 862 | the equivalent stream manual operations to give a measure of the overhead |
|---|
| 863 | incurred. The result may greatly depend on the compiler, standard library |
|---|
| 864 | implementation, and the precise choice of format-string and arguments.</p> |
|---|
| 865 | |
|---|
| 866 | <p>Since common stream implementations eventually call functions of the |
|---|
| 867 | printf family for the actual formatting of numbers, in general printf will |
|---|
| 868 | be noticeably faster than the direct stream operations And due to to the |
|---|
| 869 | reordering overhead (allocations to store the pieces of string, stream |
|---|
| 870 | initialisation at each item formatting, ..) the direct stream operations |
|---|
| 871 | would be faster than boost::format, (one cas expect a ratio ranging from 2 |
|---|
| 872 | to 5 or more)</p> |
|---|
| 873 | |
|---|
| 874 | <p>When iterated formattings are a performance bottleneck, performance can |
|---|
| 875 | be slightly increased by parsing the format string into a format object, |
|---|
| 876 | and copying it at each formatting, in the following way.</p> |
|---|
| 877 | |
|---|
| 878 | <blockquote> |
|---|
| 879 | <pre> |
|---|
| 880 | const boost::format fmter(fstring); |
|---|
| 881 | dest << boost::format(fmter) % arg1 % arg2 % arg3 ; |
|---|
| 882 | </pre> |
|---|
| 883 | </blockquote> |
|---|
| 884 | |
|---|
| 885 | <p>As an example of performance results, the author measured the time of |
|---|
| 886 | execution of iterated formattings with 4 different methods</p> |
|---|
| 887 | |
|---|
| 888 | <ol> |
|---|
| 889 | <li>posix printf</li> |
|---|
| 890 | |
|---|
| 891 | <li>manual stream output (to a dummy <i>nullStream</i> stream sending the |
|---|
| 892 | bytes into oblivion)</li> |
|---|
| 893 | |
|---|
| 894 | <li>boost::format copied from a const object as shown above</li> |
|---|
| 895 | |
|---|
| 896 | <li>the straigt boost::format usage</li> |
|---|
| 897 | </ol> |
|---|
| 898 | |
|---|
| 899 | <p>the test was compiled with g++-3.3.3 and the following timings were |
|---|
| 900 | measured (in seconds, and ratios) :</p> |
|---|
| 901 | |
|---|
| 902 | <blockquote> |
|---|
| 903 | <pre> |
|---|
| 904 | string fstring="%3$0#6x %1$20.10E %2$g %3$0+5d \n"; |
|---|
| 905 | double arg1=45.23; |
|---|
| 906 | double arg2=12.34; |
|---|
| 907 | int arg3=23; |
|---|
| 908 | |
|---|
| 909 | - release mode : |
|---|
| 910 | printf : 2.13 |
|---|
| 911 | nullStream : 3.43, = 1.61033 * printf |
|---|
| 912 | boost::format copied : 6.77, = 3.1784 * printf , = 1.97376 * nullStream |
|---|
| 913 | boost::format straight :10.67, = 5.00939 * printf , = 3.11079 * nullStream |
|---|
| 914 | |
|---|
| 915 | - debug mode : |
|---|
| 916 | printf : 2.12 |
|---|
| 917 | nullStream : 3.69, = 1.74057 * printf |
|---|
| 918 | boost::format copied :10.02, = 4.72642 * printf , = 2.71545 * nullStream |
|---|
| 919 | boost::format straight :17.03, = 8.03302 * printf , = 4.61518 * nullStream |
|---|
| 920 | </pre> |
|---|
| 921 | </blockquote><a name="extract" id="extract"></a> |
|---|
| 922 | <hr> |
|---|
| 923 | |
|---|
| 924 | <h2>Class Interface Extract</h2> |
|---|
| 925 | |
|---|
| 926 | <blockquote> |
|---|
| 927 | <pre> |
|---|
| 928 | namespace boost { |
|---|
| 929 | |
|---|
| 930 | template<class charT, class Traits=std::char_traits<charT> > |
|---|
| 931 | class basic_format |
|---|
| 932 | { |
|---|
| 933 | public: |
|---|
| 934 | typedef std::basic_string<charT, Traits> string_t; |
|---|
| 935 | typedef typename string_t::size_type size_type; |
|---|
| 936 | basic_format(const charT* str); |
|---|
| 937 | basic_format(const charT* str, const std::locale & loc); |
|---|
| 938 | basic_format(const string_t& s); |
|---|
| 939 | basic_format(const string_t& s, const std::locale & loc); |
|---|
| 940 | basic_format& operator= (const basic_format& x); |
|---|
| 941 | |
|---|
| 942 | void clear(); // reset buffers |
|---|
| 943 | basic_format& parse(const string_t&); // clears and parse a new format string |
|---|
| 944 | |
|---|
| 945 | string_t str() const; |
|---|
| 946 | size_type size() const; |
|---|
| 947 | |
|---|
| 948 | // pass arguments through those operators : |
|---|
| 949 | template<class T> basic_format& operator%(T& x); |
|---|
| 950 | template<class T> basic_format& operator%(const T& x); |
|---|
| 951 | |
|---|
| 952 | // dump buffers to ostream : |
|---|
| 953 | friend std::basic_ostream<charT, Traits>& |
|---|
| 954 | operator<< <> ( std::basic_ostream<charT, Traits>& , basic_format& ); |
|---|
| 955 | |
|---|
| 956 | // Choosing which errors will throw exceptions : |
|---|
| 957 | unsigned char exceptions() const; |
|---|
| 958 | unsigned char exceptions(unsigned char newexcept); |
|---|
| 959 | |
|---|
| 960 | // ............ this is just an extract ....... |
|---|
| 961 | }; // basic_format |
|---|
| 962 | |
|---|
| 963 | typedef basic_format<char > format; |
|---|
| 964 | typedef basic_format<wchar_t > wformat; |
|---|
| 965 | |
|---|
| 966 | |
|---|
| 967 | // free function for ease of use : |
|---|
| 968 | template<class charT, class Traits> |
|---|
| 969 | std::basic_string<charT,Traits> str(const basic_format<charT,Traits>& f) { |
|---|
| 970 | return f.str(); |
|---|
| 971 | } |
|---|
| 972 | |
|---|
| 973 | |
|---|
| 974 | } // namespace boost |
|---|
| 975 | </pre> |
|---|
| 976 | </blockquote> |
|---|
| 977 | <hr> |
|---|
| 978 | <a name="rationale" id="rationale"></a> |
|---|
| 979 | |
|---|
| 980 | <h2>Rationale</h2> |
|---|
| 981 | |
|---|
| 982 | <p>This class's goal is to bring a better, C++, type-safe and |
|---|
| 983 | type-extendable <i>printf</i> equivalent to be used with |
|---|
| 984 | streams.</p>Precisely, <b>format</b> was designed to provide the following |
|---|
| 985 | features : |
|---|
| 986 | |
|---|
| 987 | <ul> |
|---|
| 988 | <li>support positional arguments (required for internationalisation)</li> |
|---|
| 989 | |
|---|
| 990 | <li>accept an unlimited number of arguments.</li> |
|---|
| 991 | |
|---|
| 992 | <li>make formatting commands visually natural.</li> |
|---|
| 993 | |
|---|
| 994 | <li>support the use of manipulators to modify the display of an argument. |
|---|
| 995 | in addition to the format-string syntax.</li> |
|---|
| 996 | |
|---|
| 997 | <li>accept any types of variables, by relying on streams for the actual |
|---|
| 998 | conversion to string. This specifically concerns user-defined types, for |
|---|
| 999 | which the formatting options effects should be intuitively natural.</li> |
|---|
| 1000 | |
|---|
| 1001 | <li>provide printf-compatibility, as much as it makes sense in a |
|---|
| 1002 | type-safe and type-extendable context.</li> |
|---|
| 1003 | </ul> |
|---|
| 1004 | |
|---|
| 1005 | <p>In the process of the design, many issues were faced, and some choices |
|---|
| 1006 | were made, that might not be intuitively right. But in each case they were |
|---|
| 1007 | taken for <a href="choices.html">some reasons</a>.</p> |
|---|
| 1008 | <hr> |
|---|
| 1009 | |
|---|
| 1010 | <h2>Credits</h2> |
|---|
| 1011 | |
|---|
| 1012 | <p>The author of Boost format is Samuel Krempp. He used ideas from |
|---|
| 1013 | Rüdiger Loos' format.hpp and Karl Nelson's formatting classes.</p> |
|---|
| 1014 | <hr> |
|---|
| 1015 | |
|---|
| 1016 | <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= |
|---|
| 1017 | "http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" |
|---|
| 1018 | height="31" width="88"></a></p> |
|---|
| 1019 | |
|---|
| 1020 | <p>Revised |
|---|
| 1021 | <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->02 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38510" --></p> |
|---|
| 1022 | |
|---|
| 1023 | <p><i>Copyright © 2002 Samuel Krempp</i></p> |
|---|
| 1024 | |
|---|
| 1025 | <p><i>Distributed under the Boost Software License, Version 1.0. (See |
|---|
| 1026 | accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or |
|---|
| 1027 | copy at <a href= |
|---|
| 1028 | "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> |
|---|
| 1029 | </body> |
|---|
| 1030 | </html> |
|---|