Boost logo

Boost :

Subject: Re: [boost] [lexical_cast] efficiency
From: Domagoj Saric (dsaritz_at_[hidden])
Date: 2010-02-08 15:54:02

"Alexander Nasonov" <alnsn_at_[hidden]> wrote in message
> At some point in the past, I was considering a conversion to
> boost::array<char,N>.
> See, especially
> boost::array<char, 3 +
> std::numeric_limits<int>::digits10> itoa(int n);
> and
> char buf[sizeof itoa(n)];
> strcpy(buf, itoa(n).elems);
> Unfortunately, sizeof trick can't be applied to lexical_cast because the
> target type
> must be explicit.

Interesting read :)

anyways...there are still a few possible solutions for the explicit target type
issue (albeit not of the most beautiful kind ;-) :
- a meta-function returning an optimal string representation for a given type
    e.g. lexical_cast_string<T>::type
this would give
    lexical_cast<lexical_cast_string<unsigned int>::type>( 321 )
which is a 'bit' ugly and redundantly verbose (considering that the source type
is specified twice, both explicitly and implicitly)...
it can perhaps be enhanced by changing the meta-function into a metafunction
    e.g. lexical_cast_string::apply<T>::type
now the source type would have to be specified 'twice' only if someone would
want to store the result instead of passing it along ( std::puts(
lexical_cast<lexical_cast_string>( 321 ) ) ... this could further give a single
template parameter version of lexical_cast that uses
lexical_cast_string::apply<SourceType>::type for its return type ...)..

- as suggested before, overloads accepting externally allocated target/output
'ranges' can be provided (this then also leaves the space for error codes
instead of exceptions)

- lexical_cast<(t)char (const) *> specializations for built-in types that
actually return boost::arrays (that is, in such a case the explicitly specified
target type would differ from the actual target type) or (thread-local) static

>> Well, as a small immediate space/bloat-wise improvement you could extract
>> the
>> exception throwing code into a non template function and add a
>> lexical_cast<>
>> specific (instead of the global BOOST_NO_TYPEID) configuration option for
>> turning off RTTI information in bad_lexical_cast...
> I'm aware of this technique. In some cases it turns inline functions
> uninlined
> by a compiler to inlined function.

Sure, without moving the implementation into a .cpp file and/or using
'noinline'-like compiler intrisincs some compilers will still inline the code
in question but this is not an issue as you simply get the same (binary) code
as before...OTOH most compilers will, I suspect, 'properly ignore the inline
keyword' (required by a .hpp non-template function) and 'do the right thing'...

I've used this technique with MSVC++ many times and it mostly worked as

In any case, it is a safe and trivial modification, taking less time than this
post ;)

>> > C and C++ locate are not neccessarily equal.
>> In what way? wouldn't that imply that one of them is 'wrong'/'incorrect'?
> One can set two different locales in C++ program with C and C++ interface.

Ah yes... :)

> You can't use C functions from C++ without saving the old C locale and
> restoring
> it after a conversion. Now, if you take into account multi-threading ...

Maybe multi-threaded CRTs that support per-thread locales can help/be used...

In any case the support for the 'use C locale' macro can be extended to work
both that if it is specified the CRT functions are used in the
string-to-binary direction also...

A 'use no/default/ASCII local' macro would also be welcomed (enabling the use
of the most straightforward itoa/atoi-like implementations)

>> > I'm afraid it's too late to change lexical_cast, it's already in the next
>> > standard.
>> Why? As argued earlier 'the standard' should not be some untouchable
>> god-like
>> entity.
> That's right, but if all votes have already been counted, there is no much
> you can do.

I have to repeat my argument(s) ;) :
 - changing boost::lexical_cast<> does not change std::lexical_cast<>
   (unfortunately :)
  - replacing the 'screaming' ;) implementation with C functions, Spirit or
  something else does not necessarily change the interface or the behaviour
  - adding overloads that accept or return error codes instead of exceptions,
  fixed char buffers instead of std::strings also does not change the existing

<rant mode>
Sometimes it seems to me like there is a tendency to 'cram' as much 'Joe
Sixpack' functionality as possible into the standard C++ library with less
regard to efficiency and configurability as if to bring the C++ standard
library 'up to speed' with the 'competing offers by C# and Java'. IMO this
looks like an oxymoronic effort (and in contradiction to the 'you do not
pay...' 'prime directive') because no amount of effort will ever 'convert' a
'managed soul'...while OTOH the only ones that have a chance of accepting the
'C++ word', the C programmers, will be further 'repulsed' by such practice that
only gives more fuel to Linus Torvalds' irrational anti-C++ rants...
</rant mode>

I hope that the official std::lexical_cast<> specification does not encourage,
or worse imply or mandate, an implementation in terms of std::screams because
IMHO even from a design POV it flows natural that std::streams should be
implemented using lexical_cast<> functionality (for the appropriate
conversions), not vice verse...

 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley 

Boost list run by bdawes at, gregod at, cpdaniel at, john at