Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of boost. Click here for the latest Boost documentation.

Header boost/lexical_cast.hpp


Motivation

Sometimes a value must be converted to a literal text form, such as an 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:

The standard C functions typified by 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.


Examples

The following example treats command line arguments as a sequence of numeric data:
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);
        }
    }
    ...
}
The following example uses numeric data in a string expression:
void log_message(const std::string &);

void log_errno(int yoko)
{
    log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
}

Synopsis

Library features defined in "boost/lexical_cast.hpp":
namespace boost
{
    class bad_lexical_cast;
    template<typename Target, typename Source>
      Target lexical_cast(const Source& arg);
}
Unit test defined in "lexical_cast_test.cpp".


lexical_cast

template<typename Target, typename Source>
  Target lexical_cast(const Source& arg);
Returns the result of streaming 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:

The character type of the underlying stream is assumed to be 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

class bad_lexical_cast : public std::bad_cast
{
public:
    ... // same member function interface as std::exception
};
Exception used to indicate runtime lexical_cast failure.

Frequently Asked Questions

Q: Why does lexical_cast<int8_t>("127") throw bad_lexical_cast?
A: The type int8_t is a typedef to char or signed 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 or short 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 an int8_t or uint8_t not do what I expect?
A: As above, note that int8_t and uint8_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 my operator>> 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 your operator>> conform to the standard. Read a good C++ book, study std::sentry and ios_state_saver.

References

Changes

August, October 2006:

June 2005:

Earlier:


© Copyright Kevlin Henney, 2000–2005