|
Boost : |
From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-07-23 20:43:31
>From: "Gennaro Prota" <gennaro_prota_at_[hidden]>
By the way, there's a question to Gennadiy in this posting, as well.
>>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.
>If you managed to make it work with MSVC++ too, this is by far better
>than the "solution" I suggested.
I'm glad you asked. Yes. :) That was one of the design goals, to make it as
least as portable as the original. In the cases where a compiler lacks
partial specialisation, or it can't handle it, it uses simulated partial
specialisation. I used a way posted by Mat Marcus, a while ago, involving
compile.time if. This means the code is standard C++, as well. In other
words, it doesn't use the VC "hack", that is used by e.g. the VC7 port of
Loki. In this case, that couldn't be used, because it was supposed to work
on other compilers, which couldn't handle the partial specialisation, as
well, such as Borland C++ Builder.
I had the following design goals for the new version of lexical_cast:
- Fixing the problems with the original, characters or strings with
whitespace, or empty strings. Support for wide characters.
- Optimisations where appropriate. This happens automatically with the
specialisations in the previous point, including a specialisation for source
and target being the same type. Also optimisations for the source argument,
passing it by const reference, where appropriate. It uses boost::call_traits
for this.
These coincide with the "Future directions" point 1 and 2 in the
lexical_cast documentation. The 3rd point involves a possible separate
component, interpret_cast. The 4th point is a non-direction, which of course
is not followed.
Furthermore, I had the additional goals:
- At least as portable as the original (both across compilers, and in terms
of using only standard C++).
- At least as fast as the original (run-time).
- About the same time to compile.
- Compiled instantiation just as small, or smaller.
All these goals have been met.
By the way, your solution was ok, too, and I've tried that too, as
mentioned. It would let you configure the stream, to control things like
formatting. However, as we know, passing additional arguments wasn't an
option, here. Here's Kevlin's reply, when I suggested the same
(http://lists.boost.org/MailArchives/boost/msg30211.php). :)
You may wonder why I, and not Kevlin, did this. Well, as I understand, he's
quite busy, and as I had been working on an earlier version (as referred to
in the link above), and since lexical_cast really needed fixing, to handle
the problems, and possibly handle other character types, he suggested that I
could make a proposition, that he could review.
Others have also made propositions, such as Gennadiy's propositions, here
(http://groups.yahoo.com/group/boost/files/lexical_cast_propositions/), for
both updating (one of the files), and adding a wrapper (the other file),
which may be used together with lexical_cast. The update proposition
involves a possible speedup, if a string is used as the source, by
initialising the stringstream with it, rather than default-constructing
stringstream, and then reading the string in. I've tried this, too, and
timed it, but I found hardly any time differerence on my implementation, at
least (Intel C++ and STLPort). I didn't check this proposition out before I
sent it off to Kevlin, though, but based on these results, it may not be
much point in adding these special cases. It doesn't really matter to me. If
it would be desired to add it, it could be done, of course.
If Gennadiy reads this, what do you think? Have you done some timing tests,
comparing the version with and without? If so, and if you found a reasonable
difference, could you perhaps have mailed the timing-test to me?
>>To quote from the CVS lexical_cast docs:
>>
>>- 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.
>Ooppsss... I didn't look at the CVS documentation. The official one is
>quite different. In particular there are no non-directions :-)
Yeah, I know. It has relatively recently been updated by Kevlin, to clarify
things, but unfortunately, the version on the Boost site hasn't been updated
from the CVS version. Does anyone know when such syncronization would
happen? At the next official Boost release? In that case, when might that
be?
>>> > However, I have managed to solve the problem
>>> >with the introduction of a second template function, as shown below.
>This was what Craig said. My reply was only meant to show that it was
>possible to use the same name for both function templates, even with
>the broken VC++.
Indeed.
>As I said, it is a very ugly solution and I was
>against the idea of changing the interface, except if someone found
>some good use of the new parameter (the interpreter). In any case I'm
>much more happy with your solution.
Thanks. :) Yes, with the type deduction used, you won't have to specify the
character type used for the interpreter. It also works for things like:
int n=lexical_cast<int>(L"123");
If you try to use two different character types for the source and target,
it gives a compile-time error. This is reasonable, as it's not necessarily a
one-to-one mapping from one character type to another.
>>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.
>Good. So we'll wait for the upload! :-)
Perhaps the mantenance wizard, Björn Karlsson, could prod Kevlin a little on
this, too? :) So that he gets to review this version. I haven't heard from
Björn, either.
Regards,
Terje
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk