lexical_cast


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 relatively high entry level requires an extreme degree of involvement for simple conversions.

The lexical_cast template function 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.


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 "lexical_cast.hpp":
namespace boost
{
    class bad_lexical_cast;
    template<typename Target, typename Source>
      Target lexical_cast(Source arg);
}
Test harness defined in "test-lexical_cast.cpp".


lexical_cast

template<typename Target, typename Source>
  Target lexical_cast(Source arg);
Returns the result of streaming arg into a std::stringstream and then out as a Target object. The conversion is parameterized by the current lexical_context, if set. If the conversion is unsuccessful, a bad_lexical_cast exception is thrown if the current lexical_context is set for throwing or if there is no current lexical_context set, otherwise a Target() is returned.

The requirements on the argument and result types are:


bad_lexical_cast

class bad_lexical_cast : public std::bad_cast
{
public:
    virtual const char * what() const throw();
};
Exception used to indicate runtime lexical_cast failure.


Portability

To date the code and test harness have been compiled successfully using Microsoft Visual C++ 6.0, Borland C++ 5.5, and GNU g++ 2.91. Tests have run successfully for Microsoft Visual C++ 6.0 and Borland C++ 5.5. For g++ streams interpret any integer, rather than just 0 and 1, as valid for bool; the other tests pass without problem. The deprecated standard header <strstream> is used in preference to the standard <sstream> header for out-of-the-box g++ support.


Future directions


© Copyright Kevlin Henney, 2000