lexical_cast
bad_lexical_cast
int
represented as a string
, or vice-versa, when a string
is interpreted as an int
. Such examples are common when converting
between data types internal to a program and representation external to a
program, such as windows and configuration files.
The standard C and C++ libraries offer a number of facilities for performing such conversions. However, they vary with their ease of use, extensibility, and safety.
For instance, there are a number of limitations with the family of standard C
functions typified by atoi
:
sprintf
function, or the loss of
portability associated with non-standard functions such as itoa
.
int
, long
, and double
.
complex
or rational
.
strtol
have the same basic
limitations, but offer finer control over the conversion process. However, for
the common case such control is often either not required or not used. The scanf
family of functions offer even greater control, but also lack safety and ease
of use.
The standard C++ library offers stringstream
for the kind of
in-core formatting being discussed. It offers a great deal of control over the
formatting and conversion of I/O to and from arbitrary types through text.
However, for simple conversions direct use of stringstream
can be
either clumsy (with the introduction of extra local variables and the loss of
infix-expression convenience) or obscure (where stringstream
objects are created as temporary objects in an expression). Facets provide a
comprehensive concept and facility for controlling textual representation, but
their perceived complexity and high entry level requires an extreme degree of
involvement for simple conversions, and excludes all but a few programmers.
The lexical_cast
function template offers a convenient and
consistent form for supporting common conversions to and from arbitrary types
when they are represented as text. The simplification it offers is in
expression-level convenience for such conversions. For more involved
conversions, such as where precision or formatting need tighter control than is
offered by the default behavior of lexical_cast
, the conventional
stringstream
approach is recommended. Where the conversions are
numeric to numeric, numeric_cast
may offer more reasonable behavior than lexical_cast
.
For a good discussion of the options and issues involved in string-based
formatting, including comparison of stringstream
, lexical_cast
,
and others, see Herb Sutter's article,
The String Formatters of Manor Farm.
The following example uses numeric data in a string expression:int main(int argc, char * argv[]) { using boost::lexical_cast; using boost::bad_lexical_cast; std::vector<short> args; while(*++argv) { try { args.push_back(lexical_cast<short>(*argv)); } catch(bad_lexical_cast &) { args.push_back(0); } } ... }
void log_message(const std::string &); void log_errno(int yoko) { log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko)); }
"boost/lexical_cast.hpp"
:
Unit test defined innamespace boost { class bad_lexical_cast; template<typename Target, typename Source> Target lexical_cast(const Source& arg); }
"lexical_cast_test.cpp"
.
lexical_cast
Returns the result of streamingtemplate<typename Target, typename Source> Target lexical_cast(const Source& arg);
arg
into a
standard library string-based stream and then out as a Target
object.
Where Target
is either std::string
or std::wstring
, stream extraction takes the whole content
of the string, including spaces, rather than relying on the default
operator>>
behavior.
If the conversion is unsuccessful, a
bad_lexical_cast
exception is thrown.
The requirements on the argument and result types are:
Source
is OutputStreamable, meaning that an operator<<
is defined that takes a std::ostream
or std::wostream
object on the
left hand side and an instance of the argument type on the right.
Target
is InputStreamable, meaning that an operator>>
is defined that takes a std::istream
or std::wistream
object on the left hand side
and an instance of the result type on the right.
Target
is CopyConstructible [20.1.3].
Target
is DefaultConstructible, meaning that it is possible
to default-initialize an object of that type [8.5, 20.1.4].
char
unless
either the Source
or the Target
requires wide-character
streaming, in which case the underlying stream uses wchar_t
.
Source
types that require wide-character streaming are wchar_t
,
wchar_t *
, and std::wstring
. Target
types that
require wide-character streaming are wchar_t
and std::wstring
.
Where a higher degree of control is required over conversions, std::stringstream
and std::wstringstream
offer a more appropriate path. Where non-stream-based conversions are
required, lexical_cast
is the wrong tool for the job and is not special-cased for such scenarios.
bad_lexical_cast
Exception used to indicate runtimeclass bad_lexical_cast : public std::bad_cast { public: ... // same member function interface as std::exception };
lexical_cast
failure.
BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
#define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE or, g++ -DBOOST_LEXICAL_CAST_ASSUME_C_LOCALE ... (gcc on Linux/Unix) cl.exe /DBOOST_LEXICAL_CAST_ASSUME_C_LOCALE ... (Visual C++ on Windows)Eliminate an overhead ofstd::locale
if your program runs in the "C" locale. If the option is set but a program runs in other locale,lexical_cast
result is unspecified.
Frequently Asked Questions
Q: Why does
lexical_cast<int8_t>("127")
throwbad_lexical_cast
?
A: The typeint8_t
is a typedef tochar
orsigned char
. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown.Please use other integer types such as
int
orshort int
. If bounds checking is important, you can also call numeric_cast:numeric_cast<int8_t>(lexical_cast<int>("127"));Q: What does
lexical_cast<std::string>
of anint8_t
oruint8_t
not do what I expect?
A: As above, note thatint8_t
anduint8_t
are actually chars and are formatted as such. To avoid this, cast to an integer type first:lexical_cast<std::string>(static_cast<int>(n));Q: The implementation always resets the
ios_base::skipws
flag of an underlying stream object. It breaks myoperator>>
that works only in presence of this flag. Can you remove code that resets the flag?
A: May be in a future version. There is no requirement in [N1973] to reset the flag but remember that [N1973] is not yet accepted by the committee. By the way, it's a great opportunity to make youroperator>>
conform to the standard. Read a good C++ book, studystd::sentry
and ios_state_saver.References
- [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2, N1973.
- [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast, Overload #74 (PDF), August 2006.
Changes
August, October 2006:
- Better performance for many combinations of
Source
andTarget
types. Refer to [Tuning] for more details.June 2005:
- Call-by-const reference for the parameters. This requires partial specialization of class templates, so it doesn't work for MSVC 6, and it uses the original pass by value there.
- The MSVC 6 support is deprecated, and will be removed in a future Boost version.
Earlier:
- The previous version of
lexical_cast
used the default stream precision for reading and writing floating-point numbers. For numerics that have a corresponding specialization ofstd::numeric_limits
, the current version now chooses a precision to match.
- The previous version of
lexical_cast
did not support conversion to or from any wide-character-based types. For compilers with full language and library support for wide characters,lexical_cast
now supports conversions fromwchar_t
,wchar_t *
, andstd::wstring
and towchar_t
andstd::wstring
.
- The previous version of
lexical_cast
assumed that the conventional stream extractor operators were sufficient for reading values. However, string I/O is asymmetric, with the result that spaces play the role of I/O separators rather than string content. The current version fixes this error forstd::string
and, where supported,std::wstring
:lexical_cast<std::string>("Hello, World")
succeeds instead of failing with abad_lexical_cast
exception.
- The previous version of
lexical_cast
allowed unsafe and meaningless conversions to pointers. The current version now throws abad_lexical_cast
for conversions to pointers:lexical_cast<char *>("Goodbye, World")
now throws an exception instead of causing undefined behavior.
© Copyright Kevlin Henney, 20002005