
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