[Review] Boost.Convert library, new subversion URL

This is a reminder that formal review of the Boost.Convert library by Vladimir Batov starts today, April 23, and is scheduled to last through May 2. *************** * Its Purpose * *************** The library builds on the past boost::lexical_cast experience, then takes those conversion-related ideas further to suit better today's applications and programing needs. It still offers simple, minimal interface, familiar conversion behavior and additionally provides: * throwing and non-throwing conversion-failure behavior; * support for the default/fallback value to be returned when conversion fails; * two types of the conversion-failure check - basic/simple and better/safe; * formatting support based on the standard std::streams and std::stream-based manipulators (like std::hex, std::scientific, etc.); * support for different locales; * support for boost::range-compliant char and wchar_t-based containers; * no DefaultConstructibility requirement for the Target/Destination type; * consistent framework to uniformly incorporate any type-to-type conversions, extensibility and additional room to grow. With its present support for string-to-type and type-to-string conversions it is an essential tool for applications making extensive use of configuration or MS-Windows-Registry-style files or having to process/prepare considerable amounts of data in, say, XML, etc. More so, it is easily extendable to accommodate, specialize and uniformly deploy new user-defined type-to-type conversions. ******************* * Where to get it * ******************* Normally you can find Boost.Convert here: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-string-convert.zip However because the boostpro web site is having problems and will likely be down for the weekend, I have put the library into the Boost sandbox temporarily, since the Boost sandbox is up. So you can get the library, using Subversion, from https://svn.boost.org/svn/boost/sandbox/convert. This is exactly the same as the vault with the files unzipped. The HTML documentation is part of the distribution and can be found at libs/convert/index.html in the distribution above. ******************** * Writing a review * ******************** The reviews and all comments should be submitted to the developers list, and the email should have "[convert] Review" at the beginning of the subject line to make sure it's not missed. Please explicitly state in your review whether the library should be accepted. The general review checklist: - What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With what compiler? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain? And finally, every review should answer this question: - Do you think the library should be accepted as a Boost library? Be sure to say this explicitly so that your other comments don't obscure your overall opinion. Edward Diener, Review Manager

On 23/04/11 15:23, Edward Diener wrote:
This is a reminder that formal review of the Boost.Convert library by Vladimir Batov starts today, April 23, and is scheduled to last through May 2.
<snip>
******************* * Where to get it * *******************
Normally you can find Boost.Convert here:
http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-string-convert.zip
However because the boostpro web site is having problems and will likely be down for the weekend, I have put the library into the Boost sandbox temporarily, since the Boost sandbox is up. So you can get the library, using Subversion, from https://svn.boost.org/svn/boost/sandbox/convert. This is exactly the same as the vault with the files unzipped.
The HTML documentation is part of the distribution and can be found at libs/convert/index.html in the distribution above.
For those who would like to not have to type the link themselves, the docs are at: <https://svn.boost.org/svn/boost/sandbox/convert/libs/convert/index.html> John Bytheway

Edward Diener wrote:
What is your evaluation of the design?
Easy to use, powerful, and flexible. While the current implementation doesn't offer much optimization, the interface doesn't preclude doing so, except that there is no way to select the backend for the conversions. Stream-based conversions are slow, but flexible and extensible. Other sorts of conversions are useful, too. For example, while forgoing locale and manipulator support, strtol() or boost::spirit::qi::int_ are much more efficient. It would be good to have a means to access such conversions when applicable, falling back on streams-based conversions when necessary. (Perhaps this could be added as some interface in a separate namespace that falls back on the current interfaces, but some thought in this direction is warranted before the current design is cast in stone.) One thing lacking is an interface allowing the compiler to deduce the target type: int i; convert(i, str); or: int i; convert(i)::from(str); Such an interface can be built atop what is now provided, of course.
What is your evaluation of the implementation?
No.
What is your evaluation of the documentation?
[Detailed comments on the documentation follow my answers to the standard questions.] The documentation covers most of the features of the library, but can be made more complete and clearer. As noted by others, the reference section needs work, including information on exceptions and points of customization that influence particular functions. Inclusion of headers that have not value to a user of the library is questionable. For example, the linke <boost/convert/boost_parameter_ext.hpp> is nearly useless except as a means to view the header from a browser. There should be example code for each point of customization in the library so that users understand exactly how the library can be extended.
What is your evaluation of the potential usefulness of the library?
The library has the potential to be highly useful. The interface isn't as straightforward as that of lexical_cast, but is more powerful and flexible. Thus, it may not quite supplant lexical_cast, but it may well become the standard tool of many rather than sometimes using one or the other.
Did you try to use the library?
No.
How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
A detailed reading of the documentation. Past involvement in discussions on the design and interface of what became this library.
Are you knowledgeable about the problem domain?
With conversions and IOStreams, yes.
Do you think the library should be accepted as a Boost library?
I have mixed feelings on this. If lexical_cast can be extended, then I think most of the features of this library should be made part of lexical_cast, but that would preclude the optimized conversions I suggested earlier (when one can forgo locales and manipulators). Thus far, history has indicated that such changes are not welcome, making a library like Boost.Convert necessary. That answer is a bit ambiguous, so let me try to be clearer. If lexical_cast can be updated to address most, if not all of what Boost.Convert offers, then Boost.Convert should not be accepted. In that case, a distinct library that offers a non-stream-based means to do conversions that improves performance might be desirable. However, if lexical_cast won't be updated to include what Boost.Convert offers, then yes, Boost.Convert should be accepted, with due attention to suggestions and concerns raised during the review. I'm concerned with the small number of reviews to date. With so few reviews, one wonders whether the library should be accepted if there is so little interest. It may be that many are busy with BoostCon preparations or other intrusions of real life, but the lack of response is disconcerting. Documentation Comments __________________________________ You'll find many suggestions in the following that are stylistic, but they are motivated by a desire for improved clarity and correctness. Therefore, while my wording need not be retained, changes are needed in each case. s/extendable/extensible/ for the right meaning. s/straight-forward/straightforward/ IMO, "i.e." should always be "i.e.," because "that is" is always set off by a comma when it introduces a clause. There's no consistency in terminology for the source and destination types. For example, in some cases, the destination type is called the "target" type, while in others, it is the "result" type. In other cases, they are referenced by, apparently, the template parameter names "TypeIn" and "TypeOut." This is confusing. Code examples should use const more. For example, "int i = convert..." should be "int const i = convert..." in most (all?) cases. Code examples should always compile, even if they don't do much. For example, if (res) conversion succeeded should be something like the following: if (res) conversion_succeeded(); or this: if (res) /* conversion succeeded */; __________ Introduction The introduction, which is the first thing people will read, needs some work. Try this instead: Boost.Convert builds on the ideas of the venerable boost::lexical_cast (see lexical_cast's documentation) while offering simple, familiar conversios, using a minimal interface, while extending lexical_cast's feature set with: - Optional, non-throwing behavior on conversion failure; - Support for default/fallback values to return on conversion failure; - Extra control over conversion failure checking; - Support for Standard IOStreams manipulator-based formatting (std::hex, std::scientific, etc.); - Locale support; - Support for Boost.Range-compliant char- and wchar_t-based input ranges - Relaxed type requirements for the target/destination type: DefaultConstructible support is not required - Exstensibility Note: Boost.Convert does not aim to be a parser generator library. For serious parsing, consider Boost.Spirit. __________ Motivation The focus of this section is unusual. Normally, the Motivation section is intended to provide usage scenarios that potential users can identify with while highlighting the library's ability to help. Your focus is on why you created the library. That is, you described your own use case that led to creating the library. Put another way, what you've labeled "Motivation" is really "History" and should appear near the end of the Table of Contents. (Obviously, this history will have to be changed if this library and the Conversion library are accepted as Boost libraries.) Your specific use case, converting binary application data into string form (and back again) for XML to use in portable interprocess or inter-application communication, is fine, but must be developed further. Having done that, you need to motivate use of the library in some other cases: string-to-UDT, number-to-number, etc. conversions, all without making this section too long. In the last sentence, s/via Boost.Convert interface/via the Boost.Convert interface/. __________ Getting Started s/deployed/used/ s/the first deployment/the first form/ s/identical and as a drop-in/like a drop-in/ s/The second interface takes/The interface used in the second form requires/ s|returned if/when|returned if| s/That might be quite a deal-breaker...constructors/Forcing the DefaultConstructible requirement on target types prevents using boost::lexical_cast on some user-defined types./ s/variety of conversion deployments/variety of conversion use cases/ s/For example, an application/For example, consider an application that/ s/application needs to stay operational and to maintain its internal integrity despite the not-too-remote possibility of/application must work despite/ s/Like the following/The following code illustrates how this might be done:/ I suggest the fallback_1/2 example code should be structured like this: type1 p1 = convert...; if (p1 == fallback_1) ...; type2 p2 = convert...; if (p2 == fallback_2) ...; s/the deployment of boost::convert/using boost::convert/ s/boost::lexical_cast deployment/using boost::lexical_cast/ s/achieves that same result with/requires code like the following for the same result (less efficiently):/ s/seems the only/is the only/ __________ Better Conversion-Failure Check With convert<>::result Use a code/typewriter face for types, variable names, literals, etc. in the prose. For example, "'i2'" should be something like "<CODE>i2</CODE>" instead. The first sentence should not discuss the code below except by way of introduction. Thus: Consider the following code: int const i(convert<int>::from("not an int", -1); bool const conversion_failed(i == -1); <CODE>i</CODE> will be <CODE>-1</CODE> after the attempted conversion, so <CODE>conversion_failed</CODE> will be true. The second paragraph can then be improved by simplifying it and being more direct: Checking the returned value is straightforward, but not always correct. The problem is that <CODE>-1</CODE> is also the result of converting <CODE>"-1"</CODE> to <CODE>int</CODE>. Consequently, the fallback value must be selected carefully for each use case. There are many cases in which there are unused values of the target type that can be used as the fallback, so this form of conversion is useful and convenient in those cases. The third paragraph seems like an unfinished thought. "More so" is just out of place. Combining the third, fourth, and fifth paragraphs would be helpful: While it can be appropriate to use fallback values, thereby ignoring conversion failures, there are use cases in which conversion failures must be detected. In such cases, throwing an exception on conversion failure may be appropriate as illustrated in the following example: s/ (not to mention the heaviness of the try/catch interface which does not seem exactly fitting on such a low level)/. Not only are exceptions expensive, but even writing a try block makes the code verbose and less clear than it could be/ s/More so, some classes might fail to meet that requirement for the Target type to be DefaultConstructible/What's worse, some classes don't meet the Target type's DefaultConstructible requirement/ s/More so, the following is no good either as it does not provide a reliable detection of a conversion failure/The following illustrates that there is no useful fallback value to indicate conversion failure/ s/For situations like that/To solve such problems,/ s/That same convert::result could be deployed to work around the throwing behavior of the lexical_cast-like interface/convert::result also provides a means to avoid conversion failure exceptions/ __________ Two Behavioral Policies "The examples above demonstrate two interfaces behave differently with regard to handling conversion failures." There are no examples "above," so this statement is misplaced. Instead, change the first paragraph to the following: There are two ways that Boost.Convert handles conversion failures: s/when the fallback/when a fallback/ s/these behavior but only delay their application or execution/these behaviors; it merely delays them/ The last sentence can be made clearer: That is, attempting to retrieve a value from a convert::result returned by a failed conversion will throw an exception or return the fallback value, depending on the conversion interface used. __________ Requirements on the Argument and Result Types The first sentence is awkward. I suggest the following: Presently, string-to-type and type-to-string conversions are based upon std::stream (like boost::lexical_cast). That implies the following requirements for the source and destination types: s/TypeIn is OutputStreamable of a string-related type - a char or wchar_t-based container compatible with the boost::range concept/TypeIn must be OutputStreamable; TypeIn must be a char- or wchar_t-based type type compatible with Boost.Range/ s/TypeOut is CopyConstructible./TypeOut is CopyConstructible; __________ Integration of User-Defined Types s/uniformly via boost::convert interface/uniformly via boost::convert/ __________ Modifying Throwing Behavior The first two sentences are misplaced. The page is about modifying throwing behavior, not noting that one might be forced to use the exception throwing interface. However, the problem with this page is bigger. The first way to "modify throwing behavior" is simply to use an interface that *prevents* Boost.Convert from throwing an exception. (How client code chooses to react to a failure, including throwing the client's exception type, isn't relevant.) The real point of this page, it appears, is to show that a type without a default constructor can still be used and trigger an exception on conversion failure. Consequently, this is likely a better introductory paragraph: When converting from a type without a default constructor, it is sometimes necessary to have conversion failures trigger an exception rather than use a fallback value. To do that, use Boost.Convert's <CODE>throw_</CODE> directive: With that change, remove the initial code block and the following "or alternatively" line. s/forces to throw/causes Boost.Convert to throw/ __________ Formatted Conversions s/by deploying the standard/by using the standard/ s|// This call fails|// This conversion fails, so the fallback is used| s/is no better (or worse)/performs no better (or worse)/ s/formatting. In fact, under the hood it is std::stream-based/formatting, because it uses std::stream to do the formatting/ s/one should be looking at deploying comprehensive parsing and formatting libraries of their choice (say, Boost.Spirit might be a worthy contender)/one should consider using comprehensive parsing and formatting libraries like those in Boost.Spirit/ s/Still, one does not need a big cannon for shooting ducks (not that I approve such an activity) as one does not need a comprehensive formatter when all that is needed is/Still, the simplicity of Boost.Convert is often good enough/ __________ Locale-Based Conversions s/Locales are deployed in a similar fashion/Using locales with Boost.Convert is easy as shown by this example/ s/For the current locale being "en_AU" the/Assuming the current locale is "en_AU," the/ __________ String-To-String Conversions The first paragraph is an apology for the inclusion of a feature that shouldn't be documented as part of the reviewed library or else should be documented as an official part of the library (which reviewers could, of course, reject). Therefore, the first paragraph should be more like the following: Boost.Convert provides support for string-to-string conversions as illustrated with the following code which converts among different encodings: s/More so, a more practical (and not as remote) deployment of the string-to-string conversion might be demonstrated by the following snippet (taken from the library unit test)/The following code, taken from the unit_test library, illustrates how Boost.Convert's string-to-string conversions can be used for encrypting and decrypting a string/ s/Where my_cypher is a custom manipulator with the following signature/To enable such conversions, a custom manipulator, my_cypher, is needed:/ s/With the above-mentioned manipulator applied boost::convert keeps the type (std::string) of the source but changes (encrypts or decrypts) its representation/my_cypher encrypts or decrypts a string (without changing its encoding)/ __________ Using Boost.Convert with Standard Algorithms The introductory paragraph can be improved to something like this: Both conversion interfaces can be used with standard algorithms and work as expected: The example code warrants more discussion since it relies on non-obvious function objects. Clearly, convert<>::from<> is a function object type, but I don't recall that having been discussed previously. Even if it was, it warrants discussion in this page because of its relevance to use with standard algorithms. Consequently, the introductory paragraph might be more like this: Both conversion interfaces can be used with standard algorithms. This is possible because there are function objects underlying the behavior of Boost.Convert. Consider the following code: Then, you can call out the three function objects created in the example code and discuss their type and calling convention, etc. __________ Accessing Converters Directly The introductory paragraph is almost nonsense. I think that your intent on this page is to discuss the function objects, called _converters_ apparently, the discussion of which should precede using standard algorithms and would have precluded my comments on that section save for the need to reference this section to understand the function object behavior. Here's what I suggest for this page (which would replace all text on the page): What powers Boost.Convert are the function objects created by calling convert<Target>::from<Source>(). Those function objects, known as _converters_, can be saved for reuse, passed to a function or algorithm, or used as an unnamed temporary in the most straightforward uses of Boost.Convert. A _converter_ has the type convert<Target>::converter<Source>. The following code illustrates creating and reusing them in a single context. Refer to _Using Boost.Convert with Standard Algorithms_ for examples of using them with algorithms. __________ More About Converters, Customization, Optimization and Performance The text on this page is awkard. Here's a possible rewrite to consider: _Accessing Converters Directly_ and _Using Boost.Convert with Standard Algorithms_ discuss _converters_ and their uses in various contexts. Given that _converters_ are the heart of Boost.Convert, it should be no surprise that most of the configurability and capabilities of the library are found therein. For example, manipulator support and support for directives like throw_ and fallback_ are provided by _converters_. In the current Boost.Convert implementation, there is a generic string-to-type converter with an optimized specialization for string-to-bool conversions. That specialization does not support manipulators and is not std::stream-based, demonstrating that _converters_ need support only what is deemed necessary for a particular case. New _converters_ can be created for any Source/Target conversion pair focused on functionality or performance, as need be, and Boost.Convert will use the specializations without affecting the high level interfaces. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On May 2, 2011, at 10:58 AM, Stewart, Robert wrote:
If lexical_cast can be extended, then I think most of the features of this library should be made part of lexical_cast, but that would preclude the optimized conversions I suggested earlier (when one can forgo locales and manipulators). Thus far, history has indicated that such changes are not welcome, making a library like Boost.Convert necessary.
Along with Vladimir, I'd really like to kill this line of reasoning. Here's Kevlin's rationale, quoted in some earlier discussion. (It seems to have disappeared from the lexical_cast documentation since then.) http://lists.boost.org/Archives/boost/2005/04/84917.php
- 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.
I actually find that pretty convincing, although I'd like to see something that looks as close to lexical_cast as possible.
That answer is a bit ambiguous, so let me try to be clearer. If lexical_cast can be updated to address most, if not all of what Boost.Convert offers, then Boost.Convert should not be accepted. In that case, a distinct library that offers a non-stream-based means to do conversions that improves performance might be desirable. However, if lexical_cast won't be updated to include what Boost.Convert offers, then yes, Boost.Convert should be accepted, with due attention to suggestions and concerns raised during the review.
Note that performance concerns are out of scope of Boost.Convert.

On Mon, May 2, 2011 at 11:39 AM, Gordon Woodhull <gordon@woodhull.com> wrote:
On May 2, 2011, at 10:58 AM, Stewart, Robert wrote:
If lexical_cast can be extended, then I think most of the features of this library should be made part of lexical_cast, but that would preclude the optimized conversions I suggested earlier (when one can forgo locales and manipulators). Thus far, history has indicated that such changes are not welcome, making a library like Boost.Convert necessary.
Along with Vladimir, I'd really like to kill this line of reasoning. Here's Kevlin's rationale, quoted in some earlier discussion. (It seems to have disappeared from the lexical_cast documentation since then.)
http://lists.boost.org/Archives/boost/2005/04/84917.php
- 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.
I actually find that pretty convincing, although I'd like to see something that looks as close to lexical_cast as possible.
I would also like to voice my support of Vladimir. Parsing XML or properties files is tremendously slow using lexical_cast because of all the exceptions when all you want is a default value if something is missing. We've been down this road before, discussing extending lexical_cast and it went nowhere for a decent reason. So Vladimir's only choice was to make Convert, yet people are still voting No over this. --Michael Fawcett

On 5/2/2011 10:57 AM, Michael Fawcett wrote:
On Mon, May 2, 2011 at 11:39 AM, Gordon Woodhull<gordon@woodhull.com> wrote:
On May 2, 2011, at 10:58 AM, Stewart, Robert wrote:
If lexical_cast can be extended, then I think most of the features of this library should be made part of lexical_cast, but that would preclude the optimized conversions I suggested earlier (when one can forgo locales and manipulators). Thus far, history has indicated that such changes are not welcome, making a library like Boost.Convert necessary.
Along with Vladimir, I'd really like to kill this line of reasoning. Here's Kevlin's rationale, quoted in some earlier discussion. (It seems to have disappeared from the lexical_cast documentation since then.)
http://lists.boost.org/Archives/boost/2005/04/84917.php
- 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.
I actually find that pretty convincing, although I'd like to see something that looks as close to lexical_cast as possible.
I would also like to voice my support of Vladimir. Parsing XML or properties files is tremendously slow using lexical_cast because of all the exceptions when all you want is a default value if something is missing. We've been down this road before, discussing extending lexical_cast and it went nowhere for a decent reason. So Vladimir's only choice was to make Convert, yet people are still voting No over this. I was under the impression that it was the stringstream allocations rather than the exceptions. Unless you're generally throwing an exception for every single attribute or something.
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. I also disagree with this 2005 assertion that the lexical_cast name (or API?) is inappropriate for non-stream-based conversions. I don't understand why lexical_cast can't (for technical reasons) be
I disagree with the "*_cast must take a single argument" reasoning. I don't see why a built-in cast shouldn't take optional arguments when the context is appropriate, which is precisely the case with lexical conversion. The name of the cast isn't unformatted_lexical_cast, it's lexical_cast. So it should be able to handle formatted integers (which are perfectly valid language constructs)! And if it sometimes needs additional arguments to do that properly, so be it. None of the built-in casts do anything nearly as complicated as lexical_cast, so it's inappropriate to extrapolate their limitation to a single argument to lexical_cast. the "best_conversion" that Gordon alluded to. In 2005 there were political reasons that this didn't happen; it should be reconsidered since the author has resigned from maintaining it. Many of us use lexical_cast because of its "it just works" semantics. I expect many of us that care about performance have added the non-stream-based specializations in our local code - I know I have. And I'd probably do the same for locales if I had that requirement. Sorry for reviewing lexical_cast instead of Vladimir's convert. :( After reading the other reviews of Vladimir's library, I mirror Hartmut's summary:
To summarize: I feel uneasy to suggest accepting this library as it covers functionality which in my opinion belongs into lexical_cast<> in the first place. It is a natural extension of lexical_cast's functionality and for this reason should be merged with lexical_cast instead of being accepted as a separate library. Having two stream based conversion libraries in Boost (which moreover while complementing each other, sometimes expose different behavior) does not make any sense to me.
OTOH, the functionality exposed by convert is much needed and has to make it into Boost somehow.
It may be worth suspending this review pending a definitive discussion of lexical_cast's future because it covers so much of the same ground as lexical_cast. Has anybody ever studied what parts of boost have the most market penetration? I speculate that shared_ptr and lexical_cast are the top two but I'd like to see real numbers. I think Vladimir's contributions would get a lot more usage if we could squeeze at least some of it into lexical_cast. Perhaps lexical_cast could become a wrapper around convert (the latter providing an option for non-throwing behavior while the former maintains bad_lexical_cast). Both APIs should share the non-stream optimizations and might be able to share the locale/formatting interface modifications. -Matt

On Mon, May 2, 2011 at 12:46 PM, Matthew Chambers <matt.chambers42@gmail.com> wrote:
I was under the impression that it was the stringstream allocations rather than the exceptions. Unless you're generally throwing an exception for every single attribute or something.
Both. Optimizations to lexical_cast have been proposed before, not sure what the problem was to including them since they didn't change the interface, only changed performance. The exceptions hinder performance in cases when you are parsing a file with lots of default values being used, since lexical_cast has no behavior other than to throw for a bad value (last I used it, which is not recently). --Michael Fawcett

On May 2, 2011, at 12:46 PM, Matthew Chambers <matt.chambers42@gmail.com> wrote:
I don't understand why lexical_cast can't (for technical reasons) be the "best_conversion" that Gordon alluded to.
My objection was to using the name lexical_cast for conversions that aren't lexicographical, ie text-based. The (admittedly lame) name best_conversion is a stand-in for some library that has a way to register conversions and chooses the best (usu fastest) available route from S to T, whether lexicographical or not. I'm not super finicky about names but I don't really see why a name that's inaccurate should be chosen, just because an old library is popular. Then again I guess you could argue that best_conversion should just be lexical_cast and the behavior should be "as if lexicographical." lexicalesque_cast? ;-p

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Matthew Chambers Sent: Monday, May 02, 2011 5:47 PM To: boost@lists.boost.org Subject: Re: [boost] [convert] Boost.Convert Library Review
I don't have time a proper review (we need *much* longer review periods!), but having just read the docs and followed the discussions, I also mirror these views.
After reading the other reviews of Vladimir's library, I mirror Hartmut's summary:
To summarize: I feel uneasy to suggest accepting this library as it covers functionality which in my opinion belongs into lexical_cast<> in the first place. It is a natural extension of lexical_cast's functionality and for this reason should be merged with lexical_cast instead of being accepted as a separate library. Having two stream based conversion libraries in Boost (which moreover while complementing each other, sometimes expose different behavior) does not make any sense to me.
Does not make much sense to me either - BUT
OTOH, the functionality exposed by convert is much needed and has to make it into Boost somehow.
Strongly agree. We are missing out while trying to find the ideal solution. So I'd favour accepting Boost.Convert, but being prepared to fairly quickly deprecate/supersede it in favour of * A new version of lexical_cast which does take more arguments. and/or * a really slick version using Spirit (GSoC project?). Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

So I'd favour accepting Boost.Convert, but being prepared to fairly quickly deprecate/supersede it in favour of
* A new version of lexical_cast which does take more arguments.
and/or
* a really slick version using Spirit (GSoC project?).
FWIW, I'm going to mentor such a GSoC project this year: Finalizing Coerce - a conversion library on top of Boost.Spirit (the student is Jeroen Habraken a.k.a VeXocide). I believe this will give us the functionality you're looking for. Regards Hartmut --------------- http://boost-spirit.com

On 2 May 2011 19:30, Hartmut Kaiser <hartmut.kaiser@gmail.com> wrote:
So I'd favour accepting Boost.Convert, but being prepared to fairly quickly deprecate/supersede it in favour of
* A new version of lexical_cast which does take more arguments.
and/or
* a really slick version using Spirit (GSoC project?).
FWIW, I'm going to mentor such a GSoC project this year: Finalizing Coerce - a conversion library on top of Boost.Spirit (the student is Jeroen Habraken a.k.a VeXocide). I believe this will give us the functionality you're looking for.
It can be found over at https://svn.boost.org/svn/boost/sandbox/coerce/.
Regards Hartmut --------------- http://boost-spirit.com
Regards, Jeroen

On Mon, May 2, 2011 at 10:30, Hartmut Kaiser <hartmut.kaiser@gmail.com> wrote:
FWIW, I'm going to mentor such a GSoC project this year: Finalizing Coerce - a conversion library on top of Boost.Spirit (the student is Jeroen Habraken a.k.a VeXocide). I believe this will give us the functionality you're looking for.
I look forward to that. So much of the discussion here has been about how to provide all the extra formatting options, and using Spirit grammars certainly sounds like the logical choice.

On Monday, May 02, 2011 07:12:14 PM Paul A. Bristow wrote:
Does not make much sense to me either - BUT
OTOH, the functionality exposed by convert is much needed and has to make it into Boost somehow.
Strongly agree. We are missing out while trying to find the ideal solution.
So I'd favour accepting Boost.Convert, but being prepared to fairly quickly deprecate/supersede it in favour of
* A new version of lexical_cast which does take more arguments.
I strongly disagree here. The boost.convert interface is broken by design! It should not be accepted as it is right now. I explicitly did not give a "conditional yes", because I believe that the library will be completely different after fixing it. You apparently waited so long now. Does another half a year (or let it be a year) really make a difference?

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Thomas Heller Sent: Monday, May 02, 2011 6:38 PM To: boost@lists.boost.org Subject: Re: [boost] [convert] Boost.Convert Library Review
On Monday, May 02, 2011 07:12:14 PM Paul A. Bristow wrote:
Does not make much sense to me either - BUT
OTOH, the functionality exposed by convert is much needed and has to make it into Boost somehow.
Strongly agree. We are missing out while trying to find the ideal solution.
So I'd favour accepting Boost.Convert, but being prepared to fairly quickly deprecate/supersede it in favour of
* A new version of lexical_cast which does take more arguments.
I strongly disagree here.
The boost.convert interface is broken by design! It should not be accepted as it is right now.
I'm sure you are right - this is not the best solution. I feel it 'sort of works' but is wacky/nasty. But we have been lacking *any* solution for far too many years. Expert Boosters have expressed views on user acceptability, but the real test is use 'in anger' by real users. We won't get more than speculation until we get real feedback. I just don't want the problem kicked into the long grass again! Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

Gordon Woodhull wrote:
On May 2, 2011, at 10:58 AM, Stewart, Robert wrote:
If lexical_cast can be extended, then I think most of the features of this library should be made part of lexical_cast, but that would preclude the optimized conversions I suggested earlier (when one can forgo locales and manipulators). Thus far, history has indicated that such changes are not welcome, making a library like Boost.Convert necessary.
Along with Vladimir, I'd really like to kill this line of reasoning. Here's Kevlin's rationale, quoted in some earlier discussion. (It seems to have disappeared from the lexical_cast documentation since then.)
http://lists.boost.org/Archives/boost/2005/04/84917.php
- 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.
I actually find that pretty convincing, although I'd like to see something that looks as close to lexical_cast as possible.
I'm well aware of that. Still, there's been some discussion as to whether Kevlin is still the maintainer. If he abdicates (or has abdicated) that responsibility, then the new maintainer gets to decide the future of lexical_cast. Thus, there may yet be an opportunity to augment lexical_cast, which was my point.
That answer is a bit ambiguous, so let me try to be clearer. If lexical_cast can be updated to address most, if not all of what Boost.Convert offers, then Boost.Convert should not be accepted. In that case, a distinct library that offers a non-stream-based means to do conversions that improves performance might be desirable. However, if lexical_cast won't be updated to include what Boost.Convert offers, then yes, Boost.Convert should be accepted, with due attention to suggestions and concerns raised during the review.
Note that performance concerns are out of scope of Boost.Convert.
Why? _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On May 2, 2011, at 1:01 PM, "Stewart, Robert" <Robert.Stewart@sig.com> wrote:
Note that performance concerns are out of scope of Boost.Convert.
Why?
Because the author chose not to address them. It's not a more efficient alternative. It's just a more powerful (if wacky) interface. I'm certainly not saying that it's not an important concern! Performance is the main reason I don't use lexical_cast more.

Gordon Woodhull wrote:
On May 2, 2011, at 1:01 PM, "Stewart, Robert" <Robert.Stewart@sig.com> wrote:
Note that performance concerns are out of scope of Boost.Convert.
Why?
Because the author chose not to address them. It's not a more efficient alternative. It's just a more powerful (if wacky) interface.
I disagree. A first implementation of a library not about performance typically doesn't include many optimizations. That said, the string-to-bool converter forgoes streams to gain specialized behavior. Perhaps that wasn't purposely to get performance, but it reveals the intent that streams are not necessarily the means to the end. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

"Gordon Woodhull" <gordon@woodhull.com> wrote in message news:<7A4B6296-A86F-4BF9-ACE5-525B4052EE26@woodhull.com>...
Note that performance concerns are out of scope of Boost.Convert.
Why?
Because the author chose not to address them. It's not a more efficient alternative. It's just a more powerful (if wacky) interface.
I'm certainly not saying that it's not an important concern! Performance is the main reason I don't use lexical_cast more.
Gordon, Thank you for trying reading my mind. In this instance, I suspect, you read it wrong though. ;-) Indeed, I did not address the performance as IMHO that's an implementation detail which needs to come next -- after API/functionality has been settled on. Although I did provide a half-hearted example how to go about optimizing with string-to-bool when the time comes. If we decide to go ahead building/extending a set of converters (based on this lib. or any other lib), then I'd probably favor the user choosing which converter he/she wants by specifying #include <boost/convert/string-to-bool-fast.hpp> or #include <boost/convert/string-to-int-spirit.hpp> Something along these lines. That way stream-based converters would co-exist with some quick ones. Just a thought. V.

On Tuesday, May 03, 2011 10:33:50 AM Vladimir Batov wrote:
"Gordon Woodhull" <gordon@woodhull.com> wrote in message news:<7A4B6296-A86F-4BF9-ACE5-525B4052EE26@woodhull.com>...
Note that performance concerns are out of scope of Boost.Convert.
Why?
Because the author chose not to address them. It's not a more efficient alternative. It's just a more powerful (if wacky) interface.
I'm certainly not saying that it's not an important concern! Performance is the main reason I don't use lexical_cast more.
Gordon,
Thank you for trying reading my mind. In this instance, I suspect, you read it wrong though. ;-) Indeed, I did not address the performance as IMHO that's an implementation detail which needs to come next -- after API/functionality has been settled on. Although I did provide a half-hearted example how to go about optimizing with string-to-bool when the time comes.
If we decide to go ahead building/extending a set of converters (based on this lib. or any other lib), then I'd probably favor the user choosing which converter he/she wants by specifying
#include <boost/convert/string-to-bool-fast.hpp> or #include <boost/convert/string-to-int-spirit.hpp>
Something along these lines. That way stream-based converters would co-exist with some quick ones. Just a thought.
Wouldn't it be very tedious to incorporate the locales and formaters when using these optimizations? Have you really thought this through? Wouldn't it render all the "nice" operator overloading tricks useless? Again you claim your library to be extendable while it's not really. You have all those nice features so that you can easily use std locales and formatters (But i suspect these only work well with stdlib like streams). Once you incorporate any custom non stream based converter, all bets are off. Did I miss something obvious here?

On 5/3/2011 3:54 AM, Thomas Heller wrote:
On Tuesday, May 03, 2011 10:33:50 AM Vladimir Batov wrote:
If we decide to go ahead building/extending a set of converters (based on this lib. or any other lib), then I'd probably favor the user choosing which converter he/she wants by specifying
#include<boost/convert/string-to-bool-fast.hpp> or #include<boost/convert/string-to-int-spirit.hpp>
Something along these lines. That way stream-based converters would co-exist with some quick ones. Just a thought.
Wouldn't it be very tedious to incorporate the locales and formaters when using these optimizations? Have you really thought this through? Wouldn't it render all the "nice" operator overloading tricks useless?
Again you claim your library to be extendable while it's not really. You have all those nice features so that you can easily use std locales and formatters (But i suspect these only work well with stdlib like streams). Once you incorporate any custom non stream based converter, all bets are off. Did I miss something obvious here?
I'd be happy with Vladimir's proposal of optional optimizations but there should also be a single convenience header that represents the "best" conversion. Preferably one that provides optimal performance for common string->numeric and numeric->string without invoking spirit's headers. See Antony Polukhin's patches for lexical_cast: http://boost.2283326.n4.nabble.com/lexical-cast-version-of-lexical-cast-in-1... Antony's patch can do locale-sensitive integral conversion (preprocessor disable-able) without invoking streams at all, so it's certainly possible to extend and maintain the extra features. Of course, it does add a lot of lines of code (essentially reimplementing and improving strtol), but it's worth it IMO. -Matt
participants (12)
-
Edward Diener
-
Gordon Woodhull
-
Hartmut Kaiser
-
Jeroen Habraken
-
John Bytheway
-
Matthew Chambers
-
Michael Fawcett
-
Paul A. Bristow
-
Scott McMurray
-
Stewart, Robert
-
Thomas Heller
-
Vladimir Batov