Lumiera
0.pre.03
»edit your freedom«
|
Go to the source code of this file.
Front-end for printf-style string template interpolation.
While the actual implementation just delegates to boost::format, this front-end hides the direct dependency, additionally invokes a custom toSting conversion whenever possible, provides a direct automatic conversion to the formatted result to string and catches any exceptions.
This front-end is used pervasively for diagnostics and logging, so keeping down the compilation and object size cost and reliably handling any error is more important than the (small) performance gain of directly invoking boost::format (which is known to be 10 times slower than printf anyway).
To perform the formatting, usually a _Fmt
object is created as an anonymous temporary, but it may as well be stored into a variable. Copying is not permitted. Individual parameters are then fed for formatting through the ''
operator. Each instance of _Fmt uses its own embedded boost::format object for implementation, but this formatter resides within an opaque buffer embedded into the frontend object. The rationale for this admittedly tricky approach is to confine any usage of boost::format to the implementation translation unit (format-string.cpp).
The implementation is invoked by the frontend through a set of explicit specialisations for all the relevant primitive data types. For custom types, we prefer to invoke operator string() if possible, which is determined by a simple metaprogramming test, which is defined in lib/meta/util.pp, without relying on boost. As a fallback, for all other types without built-in or custom string conversion, we use the mangled type string produced by RTTI.
The compile time and object size overhead incurred by using this header was verified to be negligible, in comparison to using boost::format. When compiling a demo example on x86_64, the following executable sizes could be observed:
|debug | stripped
-------------------------------------—:|-—: | —: just string concatenation ... | 42k | 8.8k including and using format-string.hpp ...| 50k | 9.4k including and using boost::format ... | 420k | 140k
In addition, we need to take the implementation translation unit (format-string.cpp) into account, which is required once per application and contains the specialisations for all primitive types. In the test showed above, the corresponding object file had a size of 1300k (with debug information) resp. 290k (stripped).
The syntax of the format string is defined by boost::format and closely mimics the printf formatting directives. The notable difference is that boost::format uses the C++ stream output framework, and thus avoids the perils of printf. The individual formatting placeholders just set the corresponding flags on an embedded string stream, thus the actual parameter types cause the selection of a suitable format, not the definitions within the format string.
An illegal format string will raise an error::Fatal. Any other error during usage of the formatter is caught, logged and suppressed, inserting an error indicator into the formatted result instead
A formatter is usually created as an anonymous object, at places where a string is expected. An arbitrary number of parameters is then supplied using the ''
operator. The result can be obtained
Code example:
TICKET #1204 : proper alignment verified 10/2019
Definition in file format-string.hpp.
#include "lib/error.hpp"
#include "lib/symbol.hpp"
#include "lib/nocopy.hpp"
#include "lib/meta/util.hpp"
#include "lib/meta/size-trait.hpp"
#include <string>
Typedefs | |
typedef unsigned char | uchar |
Functions | |
void | _clear_errorflag () |
string | _log_and_stringify (std::exception const &ex) |
string | _log_unknown_exception () |
LUMIERA_ERROR_DECLARE (FORMAT_SYNTAX) | |
"Syntax error in format string for boost::format" | |
bool | operator== (_Fmt const &left, _Fmt const &right) |
bool | operator== (_Fmt const &fmt, string const &str) |
bool | operator== (_Fmt const &fmt, const char *const cString) |
bool | operator== (string const &str, _Fmt const &fmt) |
bool | operator== (const char *const cString, _Fmt const &fmt) |
Namespaces | |
lib | |
Implementation namespace for support and library code. | |