Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-07-23 13:31:02


>From: "Gennaro Prota" <gennaro_prota_at_[hidden]>

Apparently, I haven't got Craig's posting (yet), so I reply to it as well,
here.

> On Mon, 22 Jul 2002 21:44:45 +0100, "Craig Henderson"
> <cdm.henderson_at_[hidden]> wrote:
>
> >The lexical_cast<>() function does not respect character traits. I work
on a
> >Win32 platform with MSVC which supports char and wchar_t for 8-bit and
> >16-bit character representation, respectively. lexical_cast<>() uses a
> >std::stringstream which is a synonym for template class
basic_stringstream,
> >specialized for elements of type char.

I've been cooperating with Kevlin Henney and Björn Karlsson (the Boost
maintenance wizard) in making a new version of lexical_cast, which also
handles wide characters (selected by the type of the operands, so no change
to the interface is needed), as well as fixing problems with characters or
strings containing whitespace, or empty strings (which used to throw
exceptions, earlier).

I sent the new version to Kevlin and Björn a while ago, but he hasn't got
around to it, yet.

In short, this proposal has already been fixed. It's just not committed,
yet. :)

Kevlin hasn't wanted to add additional parameters, as it would then no
longer look like a cast. However, the mentioned changes can be done without
changing the interface.

To quote from the CVS lexical_cast docs:

--- Start quote ---

Future directions

- Improved string handling, correctly accommodating wide character strings,
incompatible basic_string types, and empty strings.

- Optimize the use of a stream away for identity conversions.

- 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. This would be
an interesting project, but there are no concrete plans to pursue this at
the moment.

- It is also worth mentioning future non-directions: anything that involves
adding extra arguments for a conversion operation is not being considered. A
custom keyword cast, such as lexical_cast, is intended to look like a
built-in cast operator: built-in cast operators take only a single operand.
Where a higher degree of control is required over conversions, the standard
stringstream offers a more appropriate path. Where non-stream-based
conversions are required, lexical_cast is the wrong tool for the job, and so
it won't be special-cased for such scenarios.

--- End quote ---

The first two points have been implemented in the new version of
lexical_cast. The third point describes a different component. The fourth
point describes non-directions.

> > However, I have managed to solve the problem
> >with the introduction of a second template function, as shown below.

> template<typename Target, typename Source, typename E>
> inline Target lexical_cast(Source arg, E& interpreter)
> {
> //E interpreter;
> Target result;
>
> if(!(interpreter << arg) || !(interpreter >> result) ||
> !(interpreter >> std::ws).eof())
> throw bad_lexical_cast();
>
> return result;
> }

Adding a second parameter, such as this, has been suggested earlier, too (I
had it in an earlier suggestion of lexical_cast), but has been rejected,
from what I understand from Kevlin, as is explained in "Future directions"
above here.

> The main disadvantage is that in the general case you have to pass an
> instance of the interpreter type. The main advantage (?) is that you
> are not limited to default construct it so, theoretically, you could
> pass some sort of "special interpreter".

That was my idea, too, so that you could customize the interpreter, e.g.
setting formatting, etc. However, I understand the interest in keeping this
without extra parameters.

> >Now I can use this to create a wide-character string
> >
> > std::basic_string<wchar_t> str = lexical_cast_interpreter<
> >std::basic_string<wchar_t>, int, std::basic_stringstream<wchar_t> >(123);
>
> With the code above it becomes:
>
> std::basic_stringstream<wchar_t> use_this;
>
> std::basic_string<wchar_t> str =
> lexical_cast< std::basic_string<wchar_t> >(123, use_this);

And with the new version, you can do this:

lexical_cast< std::basic_string<wchar_t> >(123);

:)

Internally, it uses specialisations, based on the source and target types,
to select character type for the interpreter. You may even use other
character types than char or wchar_t.

Regards,

Terje


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk