Boost logo

Boost :

From: Alexander Nasonov (alnsn_at_[hidden])
Date: 2006-05-01 03:51:51


Oleg Abrosimov wrote:
> [ ... skiped ... ]
> A proponents of lexical_cast<> have a point that the main
> advantage of lexical_cast<> component is its usage
> simplicity and symmetry (angle braces are used in both cases):
> int i = lexical_cast<int>("1");
> string s = lexical_cast<string>(1);
>
> Additionally, it looks like built-in casts, and it is considered as a
> very cool thing.

That's right.

> On the other side, opponents of lexical_cast<> wants more functionality
> that doesn't fit into simple cast-like usage like:
>
> The requirements table.
> 1) controlling conversions via facets (locales)
> 2) full power of iostreams in simple interface.
> All functionality accessible with iostreams
> (through manipulators) should be accessible.

For to_string functionality, you can use Boost.Format.

> 3) functor adapters to use with std algorithms
I agree, that's a nice feature. May be we could try to add lambda
support to it? Something like this: lexical_cast<_1>(_2);

> 4) error handling and reporting. (what kind of error occurred?)
> * optionally report failing without exceptions raising
> 5) best performance, especially for built-in types and for use in loops

I think that lexical_cast's performance can be improved. Yesterday I
wrote a first version of integral2str which is several times faster then
sprintf("%d"). It doesn't add thousands_sep to output but this can be
easily changed (assuming that there are 3 digits in a group).

I also like this idea:

    lexical_cast< boost::array<char, 30> >(INT_MIN);

Unlike builtin arrays, boost::array can be copied and therefore, it can
be returned from a function. We could get rid of dynamic allocations for
integral and other common types completely.
It doesn't meet InputStreamable requirements, though.

> [ ... skiped ... ]
> It is clear that lexical_cast is not intended to address (1-4) points in
> the list above,
> and even (5). For optimizing conversions in loops you'll need to resort
> to stringstreams again.

I don't think that stringstreams are the fastest.

> [ ... skiped ... ]
> There are short examples of intended usage of this library (for those
> who are too busy to read the full proposal?s text)
>
> // simple initialization usage:
> string s = string_from(1);
> int i = from_string(?1?);
>
> // embedded in expression usage:
> double d = 2 + (double)from_string(?1?);

lexical_cast can do this.

> // usage with special locale:
> string s = string_from(1, std::locale(?loc_name?));
>
> // usage with special format:
> string s = string_from(1, std::ios::hex);
>
> // usage with special format and locale:
> string s = string_from(1, std::ios::hex, std::locale(?loc_name?));

Use Boost.Format.

> [ ... skiped ... ]
>
> To optimize conversions in a loop one can do:
> string_cvt cvt(std::ios::hex, std::locale(?loc_name?));
> string s;
> for(int i; i < 100; ++i) {
> string t;
> cvt(i, t);
> s += (t + ? ?);
> }

How use of cvt differs from ostringstream?

std::ostringstream cvt;
for(int i; i < 100; ++i)
     cvt << std::hex << i;
std::string s = cvt.str();

> Details of this proposal are below:
> [ ... skiped ... ]
> int i = from_string(s);
>
> its counterpart would become:
> string s = string_from(1);
> wstring s = wstring_from(1);
>
> Note:
> 1) usage is symmetrical
> 2) no explicit template parameters
>
> The from_string function has one minor drawback:
> it can not be used in expressions without explicit casting to the type
> desired:
>
> double d = 2.0 + from_string(s); // doesn't works
> double d = 2.0 + (double)from_string(s); // does
>
> But it can be seen as an advantage, because:
> 1) intention is clear and enforced by compiler (operator'+' ambiguity,
> or run-time exception if 2.0 becomes 2 and s looks like ?1.1?)
> 2) mentally, the expression "(double)from_string(s)" is close to
> optimal, it can be thought of as:
> "Get double from string" - It is hard to imagine thinking path that is
> shorter and reflects intentions in a more straightforward way.

Disadvantages:

1) Reminds programmers of old-style casts.
2) Raise eyebrows of experienced programmers (what is a return type
   of from_string?)
3) Some coding standards prohibit old-style casts. Your example should be
   rewritten to satisfy those standards:

    double d = 2.0 + static_cast<double>(from_string(s));

It's worse then from_string<double>(s).

> [ ... skiped ... ]

-- 
Alexander Nasonov
Project Manager
http://www.akmosoft.com

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