|
View:
New views
10 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 | Next > |
|
|
Re: [convert] are you mixing default_value and error_value?On Wed, Jul 8, 2009 at 6:42 AM, vicente.botet<vicente.botet@...> wrote:
> > > Yes, this is what I wanted to say. On the case of the direction class, you are forced to give an *initial value* because direction is not default constructible, but with your interface we can't have an exception in this case. Is for this reason I say you are mixin both. > Do we need to give an initial value just for conversion to work at all, or is it only needed as a return in the error case? Tony _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?Hi It is needed for both usages: the initial value when the class is not default constructible, and the error value when we want this value to be returned when failure. Now we can not have an exception for the conversion to a class that is not default constructible because when we give a default value it is also interpreted as the error value. As I said we are mixing both concepts, which is not good, as both are orthogonal. Vicente |
|
|
Re: [convert] Now with Boost.Parameter interface.> Hartmut Kaiser <hartmut.kaiser <at> gmail.com> writes:
> > > int i = convert<int>::from(str, 0)(locale_ = new_locale)(throw_=true); > > int i = convert<int>::from(str, 0) >> new_locale >> dothrow; > > Sorry if I'm late here. Either of both ways just feels wrong as not all of > the manipulators/parameters are of general use. The radix_ parameter > described elsewhere is a good example for a parameter applicable to string > <--> integer conversion only. It is highly confusing not to get a compile > time error while specifying a wrong parameter (a parameter not being > applicable for the type to convert to/from). > > For instance, what is supposed to happen if I do: > > convert<double>::from(str, radix_ = 16) Well, I agree that "it is highly confusing not to get a compile time error while specifying a wrong parameter". Fortunately, it does not have to be that way and is up to the conversion implementer. Say, convert<double>::from(str)(radix_ = 16) convert<double>::from(str) >> std::hex Both above internally deploy a specialization of some converter<TypeIn, TypeOut>. Then, additional formatting (like op() for 'radix_=16' or op>> for '>> std::hex') is passed to *that* converter. That is the #1 above can be seen as converter<std::string, double> cvt = convert<double>::from(str); cvt(radix_ = 16); double d = cvt.operator double(); It's all up to the implementer of converter<std::string, double> to accept or reject 'radix_=16' during *compilation*. > The current approach in my view mixes things not belonging together. A > conversion library needs to keep apart data and formatting information. This > is not done here. Formatting and data type are spread over the whole > expression, making it very difficult to get things right. Well, I probably cannot fully agree with "formatting and data type are spread" as it is always data first, then the rest. Say, my typical usage is convert<double>::from(str) >> locale >> std::scientific; the first line has the data and the rest is about formatting. Even in convert<double>::from(str)(locale_=locale) >> std::scientific; it seems clear that the data comes first with everything else following. As for "conversion library needs to keep apart data and formatting" I think in 'convert' data and formatting are apart due to the conversion specification *order*. Your preference (as I understand) is to take that separation further (as in Spirit) physically separating the formatting into a separate object. > I believe this is a strength of Spirit's approach, where data and formatting > are clearly separated. Well, I'd insist on just :-) "clearer separated" as I feel 'convert' does provide that separation although not to the degree Spirit does. And here I suspect we are talking about *visual* separation as under the hood 'convert' can be as strict (data-wise and formatting-wise) as the implementer likes. > Applying a similar approach to convert would result > in: > > double d = convert::from(str, double_); > and > std::string s = convert::to(d, double_); > > where double_ is an example for a placeholder... Please bear with me as I cannot claim familiarity with Spirit. I am not sure if/how that placeholder-based approach can be uniformly extended onto user types. I'd expect something like direction d = convert::from(str, direction_); That is, for a 'direction' user type to be integrated into the 'convert' framework, the user needs do provide a 'direction_' specification. If so, then I have no serious objections against that. It's (I think) in line with what Vicente was suggesting with convert_traits and it is *somewhat* similar to the current lexical_cast/convert approach. Although lexical_cast/convert limit that "specification" to only op>> and op<<. > Spirit allows to build more complex formats/grammars out > of simpler ones, while providing all necessary primitive type conversions). > For instance, applying a different locale to this results in: > > real_spec<double> locale_double(new_locale); > double d = convert::from(str, locale_double); > and > std::string s = convert::to(d, locale_double); > > where real_spec (choose a different name, if you like) creates a new > placeholder encapsulating all formatting information needed to do the > conversion. Well, I feel you are arguing the interface -- forcing the user to provide the formatting as a separate fmt object as the following could easily have the same implementation. real_spec<double> locale_double(new_locale); double d = convert::from(str, locale_double); or double d = convert::from(str, real_spec<double>(new_locale)); or double d = convert::from(str)(real_spec<double>(new_locale)); or double d = convert::from(str).locale(new_locale); or double d = convert::from(str)(locale_=new_locale); As for the interface, your approach might well be justified for Spirit applications. From *my* usage experience of 'convert' I feel for 'convert' it'd be an overkill. Please bear in mind that lexical_cast/convert never had Spirit-like ambitions and should be never treated as a serious converter of any sort. That does not mean, I do not feel 'convert' has no place. If you like 'convert' is a bike to get a short distance from A to B quickly and without much/any preparation. Spirit is for a longer trip. My usage pattern is to get a dozen or more config. parameters, convert them to their binary form, report conversion failures and get to my main domain-specific (non-parsing-related) business. Therefore, I am only prepared to allocate 12 lines of code to convert 12 parameters and to get to my main business ASAP. > This has the additional advantage of providing a nicely extensible > framework. Any non-foreseeable formatting requirements are easily > customizable. I honestly see neither of 'convert' or Spirit approaches easier/harder to customize. That customization has to be implemented somewhere. Spirit (as I understand) does it via that "formatting specification" object. 'convert' has the converter. In fact, come to think of it now I not sure how real_spec<double> can help as TypeOut ('double' in the example) is only half of the story. Formatting equally depends on TypeIn. Say, I do not think we can allow/disallow (radix_=16) for real_spec<int> as we do not yet know if we are converting from a string. > OTOH, general parameters applying directly to the conversion process (such > as throwing behavior or default values) are fine to be passed as additional > arguments. But care must be taken not to intermix this with formatting > related parameters (and yes, believe me or not, locales _are_ formatting > related). So I think the following would be ok: > > double d = convert::from(str, double_, default_ = 0.0); > and > std::string s = convert::to(d, double_, throw_ = true); Don't you think I can apply the following *interface* transformation without undermining the actual implementation: double d = convert::from(s, double_formatter, default_ = 0.0); to double d = convert<double>::from(s, default_=0.0)(double_formatter); to double d = convert<double>::from(s,0)(double_formatter); to double d = convert<double>::from(s,0)(double_fmt_part1)(double_fmt_part2); which the current interface. ;-) > BTW: this interface above is easily implementable on top of Spirit. It's > just a thin wrapper around existing functionality. And I already expressed > my opinion that any high level conversion library should be built on top of > Spirit... I do not think anyone even argued against that. And I do not feel that hte existing interface stops us from dong that. >... - a proven, fast, reliable, versatile, and mature parser and > generator framework. :-) > Anything else leads to code duplication, > inconsistencies, implementation flaws, you name it. Well, I personally do not see code duplication, etc. what I see is different horses for different courses. With all due respect as of now I see Spirit as too big a hammer for my purposes. > Converting a string of > digits into an integer might seem to be an easy task. But it's not. It's > tricky, error prone, and difficult to get correct _and_ fast at the same > time. I surely agree. That said, in many many cases people do not need that complexity and processing power. lexical_cast (and convert -- a glorified lexical_cast) is far from perfect. However, its functionality (and often even speed) is sufficient (well, almost) and it's better known in average-user circles and easier to understand and deploy. I spend my day writing fuzzy logic related to train movements. I only care about conversions as much as reading from a config. file or reading inter-process XML. For that as of now I find Spirit too steep a ladder to claim for my current needs. It's not a criticism of any kind, just how I feel. V. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?> From: "Gottlob Frege" <gottlobfrege@...>
> > Do we need to give an initial value just for conversion to work at > all, or is it only needed as a return in the error case? The user does not provide any initial values. The only value that is provided is the failure-conversion value: int i = convert<int>::from(str, 789); '789' will only be returned if the conversion fails. As int i = convert<int>::from(str); does not provide such a conversion-failure value, we have nothing to return in case of a failure. So, we throw. Indeed, under the hood that 789 (in #1 case and int() in #2) value happens to be used for some initialization. However, IMHO it is none of user's business. V. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?> From: "Vicente Botet Escriba" <vicente.botet@...>
> ... >> Do we need to give an initial value just for conversion to work at >> all, or is it only needed as a return in the error case? >> >> Tony > > It is needed for both usages: the initial value when the class is not > default constructible, and the error value when we want this value to be > returned when failure. Now we can not have an exception for the conversion > to a class that is not default constructible because when we give a > default > value it is also interpreted as the error value. As I said we are mixing > both concepts, which is not good, as both are orthogonal. The is only *one* value provided -- a conversion-failure value. It happens to be used internally for some initialization (for std::stream-based conversions). It's an internal implementation matter and not guaranteed to be that way. What do we achieve by stressing it out? V. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?Hi, What does this does? direction d = convert<direction>::from(str); Vicente |
|
|
Re: [convert] are you mixing default_value and error_value?On Thursday, July 9, 2009, Vladimir Batov <batov@...> wrote:
> > From: "Vicente Botet Escriba" <vicente.botet@...> > ... > > Do we need to give an initial value just for conversion to work at > all, or is it only needed as a return in the error case? > > Tony > > > It is needed for both usages: the initial value when the class is not > default constructible, and the error value when we want this value to be > returned when failure. Now we can not have an exception for the conversion > to a class that is not default constructible because when we give a default > value it is also interpreted as the error value. As I said we are mixing > both concepts, which is not good, as both are orthogonal. > > > The is only *one* value provided -- a conversion-failure value. It happens to be used internally for some initialization (for std::stream-based conversions). It's an internal implementation matter and not guaranteed to be that way. What do we achieve by stressing it out? > Maybe it should not be used for initialization at all. Let's say MyClass has a bad_state setting, that, when set, stops the class from doing anything, even processing << operators. So if I pass in bad_state as a default return value, it won't work if it is internally being used as an init value. Tony > V. > > > _______________________________________________ > Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost > _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?On Thursday, July 9, 2009, Vicente Botet Escriba
<vicente.botet@...> wrote: > > > > Vladimir Batov wrote: >> >>> From: "Vicente Botet Escriba" <vicente.botet@...> >>> ... >>>> Do we need to give an initial value just for conversion to work at >>>> all, or is it only needed as a return in the error case? >>>> >>>> Tony >>> >>> It is needed for both usages: the initial value when the class is not >>> default constructible, and the error value when we want this value to be >>> returned when failure. Now we can not have an exception for the >>> conversion >>> to a class that is not default constructible because when we give a >>> default >>> value it is also interpreted as the error value. As I said we are mixing >>> both concepts, which is not good, as both are orthogonal. >> >> The is only *one* value provided -- a conversion-failure value. It happens >> to be used internally for some initialization (for std::stream-based >> conversions). It's an internal implementation matter and not guaranteed to >> be that way. What do we achieve by stressing it out? >> >> V. >> >> >> _______________________________________________ >> Unsubscribe & other changes: >> http://lists.boost.org/mailman/listinfo.cgi/boost >> >> > > Hi, > > What does this does? > > direction d = convert<direction>::from(str); > > Vicente > > Not compile, I guess. You need to either write a specialization of convert, or maybe convert_traits. You had to specialize << anyhow. Maybe the default/error form: convert<direction>::from(str, down) shouldn't compile either (ie don't use error return as init value). Tony > -- > View this message in context: http://www.nabble.com/-convert--Now-with-Boost.Parameter-interface.-tp23362838p24407682.html > Sent from the Boost - Dev mailing list archive at Nabble.com. > > _______________________________________________ > Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost > _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?Gottlob Frege wrote:
> On Thursday, July 9, 2009, Vicente Botet Escriba > <vicente.botet@...> wrote: > > > > What does this does? > > > > direction d = convert<direction>::from(str); > > Not compile, I guess. Assuming direction is the exemplar Vladimir has been using all along, that won't compile because direction has no default constructor. The underlying behavior is the same as that of lexical_cast: direction result; std::istringstream stream(str); stream >> result; return result; That requires a default constructor. This code: direction d(convert<direction>::from(str, direction::up)); avoids the need for a default constructor via code like the following: direction result(direction::up); std::istringstream stream(str); stream >> result; return result; > You need to either write a specialization of convert, or maybe > convert_traits. You had to specialize << anyhow. The traits idea is inappropriate because the value to return for each invocation can change. > Maybe the default/error form: > convert<direction>::from(str, down) > shouldn't compile either (ie don't use error return as init > value). There isn't a choice. In order to extract a direction from an istringstream, there must be a direction instance. If direction has no default constructor, then the result *must* be initialized from the error return value. I don't know what you think is or could be happening, but I hope the code I've shown above clarifies the matter. _____ Rob Stewart robert.stewart@... Software Engineer, Core Software using std::disclaimer; 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. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [convert] are you mixing default_value and error_value?On Thu, Jul 9, 2009 at 9:41 AM, Stewart, Robert<Robert.Stewart@...> wrote:
> Gottlob Frege wrote: > > Assuming direction is the exemplar Vladimir has been using all > along, that won't compile because direction has no default > constructor. The underlying behavior is the same as that of > lexical_cast: > > direction result; > std::istringstream stream(str); > stream >> result; > return result; > > That requires a default constructor. > > This code: > > direction d(convert<direction>::from(str, direction::up)); > > avoids the need for a default constructor via code like the > following: > > direction result(direction::up); > std::istringstream stream(str); > stream >> result; > return result; > > >> Maybe the default/error form: >> convert<direction>::from(str, down) >> shouldn't compile either (ie don't use error return as init >> value). > > There isn't a choice. In order to extract a direction from an > istringstream, there must be a direction instance. If direction > has no default constructor, then the result *must* be initialized > from the error return value. I don't know what you think is or > could be happening, but I hope the code I've shown above > clarifies the matter. > I'm sure you are right, and the real limitation comes down to how streams and << work. I was also trying to imagine the no_throw case: direction result(default_value); try { stream >> result; } catch (...) { result = error_value; } return result; Although I'm not even sure - if you can guarantee that "return result" doesn't throw (in some stupid complicated copy constructor) - if that is the meaning of no_throw - if that is the meaning of "error" (ie stream >> result could still have an 'error' but not have thrown, depending on how it works, and meaning, etc) - and still direction needed to be initialized, because, basically, it doesn't have a construct-from-stream: { return direction(stream); } nor do most types, thus we use >> instead, as is defacto. Basically I was leaving the implementation open to my imagination, and focusing more on how it looks from the outside. > _____ > Rob Stewart Tony _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
| < Prev | 1 - 2 - 3 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |