# Header boost/lexical_cast.hpp

- Motivation
- Examples
- Synopsis
- `lexical_cast`
- `bad_lexical_cast`
- Portability
- Future directions

## 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`:

- Conversion is supported in one direction only: from text to internal data type. Converting the other way using the C library requires either the inconvenience and compromised safety of the `sprintf` function, or the loss of portability associated with non-standard functions such as `itoa`.
- The range of types supported is only a subset of the built-in numeric types, namely `int`, `long`, and `double`.
- The range of types cannot be extended in a uniform manner. For instance, conversion from string representation to `complex` or `rational`.

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 `"boost/lexical_cast.hpp"`:

>     namespace boost
>     {
>         class bad_lexical_cast;
>         template<typename Target, typename Source>
>           Target lexical_cast(Source arg);
>     }

Test harness defined in `"lexical_cast_test.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:

- `Source` is OutputStreamable, meaning that an `operator<<` is defined that takes a `std::ostream` object on the left hand side and an instance of the argument type on the right.
- Both `Source` and `Target` are CopyConstructible [20.1.3].
- `Target` is InputStreamable, meaning that an `operator>>` is defined that takes a `std::istream` object on the left hand side and an instance of the result type on the right.
- `Target` is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.3].
- `Target` is Assignable [23.1].

## `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

- A mechanism for providing quality-of-service control is needed, e.g. formatting and exception behavior. In the name of simplicity (and release), the current version strips out an earlier experimental version.
- Wide character and incompatible `std::basic_string` issues need to be catered for.
- An `interpret_cast` that performs a do-something-reasonable conversion between types. It would, for instance, select between `numeric_cast` and `lexical_cast` based on `std::numeric_limits<>::is_specialized`.

© Copyright Kevlin Henney, 2000