Boost logo

Boost :

Subject: Re: [boost] [convert] Default Syntax Idea
From: Stewart, Robert (Robert.Stewart_at_[hidden])
Date: 2009-02-25 08:40:59


On Tuesday, February 24, 2009 5:29 PM
Vladimir.Batov_at_[hidden] wrote:
> > From: "Stewart, Robert" <Robert.Stewart_at_[hidden]>
>
> > int const i(3);
> > string const s("something");
> > int const j(convert<int>(s) | 5);
>
> Yes, this idea is similar to
>
> int j = convert<int>(s).or_default(5);
>
> but does not introduce new vocabulary (my main hesitation). With the
> suggested op|, as I am reading it, it makes perfect reading
> just like I'd
> read English. And that is usually my criterion for an
> interface. So, I am
> voting 'yes'... in principle. See further below.

I suggested it precisely because it read well. I'm glad you thought so, too.

> > convert<DestType,SourceType>(SourceType) can return a type which
> > throws on failure in operator DestType(), but has an operator
> > |(SourceType) which returns a second type constructed with the
> > SourceType value. The second type provides its own operator
> > |(SourceType) which returns that value in its operator
> DestType() on
> failure.
>
> When the user does not want comprehensive result, it works.
> The problem as
> I see it is when the user wants the comprehensive report --
> we return two
> different types,
>
> convert1<string, int> j1 = convert<string, int>(s);
> convert2<string, int> j2 = convert<string, int>(s) | 5;

I don't think that's a valid concern. The whole point of supplying a default is that there will always be a valid result. It may be the converted input or it may be the default, but the caller wants one or the other and will proceed apace.

> Sometimes I feel we need that as I might like to explicitly
> check if the
> call failed without relying on the default
>
> convert1<string, int> j1 = convert<string, int>(s) &
> boost::nothrow;
> convert2<string, int> j2 = convert<string, int>(s) | 5;
>
> if (j1 == 0 && !j1.good()) j1 = 0 but conversion failed
> if (j2 == 5 && !j1.good()) j2 = 5 but conversion failed

I can't imagine a use case for that. If the caller actually wants to know whether the conversion succeeds, the caller can attempt the conversion and if it fails, supply the default and take other actions. There's no need to support both a default and the conversion state.

> Unless we convert both convert1 and convert2 to convert<string,
> int>::result as
>
> convert<string, int>::result j1 = convert<string, int>(s) &
> boost::nothrow;
> convert<string, int>::result j2 = convert<string, int>(s) | 5;
>
> if (j1 == 0 && !j1.good()) j1 = 0 but conversion failed
> if (j2 == 5 && !j1.good()) j2 = 5 but conversion failed
>
> Or we might simplify that as
>
> convert::result<int> j1 = convert::to<int>(s) &
> boost::nothrow;
> convert::result<int> j2 = convert::to<int>(s) | 5;

I don't see that adding any value.

> if (j1 == 0 && !j1.good()) j1 = 0 but conversion failed
> if (j2 == 5 && !j1.good()) j2 = 5 but conversion failed
>
> The reason I am sticking 'to' in again is that I need the
> 'convert' as a
> namespace... or rather as a namespace-like structure:
>
> struct convert : mimic_namespace /*I have such a class*/
> {
> template<class TypeOut>
> struct result
> {
> TypeOut value_;
> bool good_;
> };
>
> struct internal_with_default { ... };
> struct internal_with_no_default { ... };
>
> template<class TypeOut, class TypeIn>
> internal_with_default<TypeOut, TypeIn>
> to(TypeIn const&);
> };

Why not spell "to" as "operator ()?"

> With namespace-like convert structure people will not be able
> to shortcut
> 'convert'. I.e. they'll always have to say
>
> convert::to

Not with a function call operator.

> > Returning a default value in lieu of an exception is a special case;
> > it ought not be treated like formatting.
>
> I have an impression that throwing/not-throwing and
> providing/not-providing the default have to be configured
> independently.
> Like I *might* need to throw even if I provide the default:
>
> direction dir = convert<string, direction>(str,
> direction::up) &
> boost::dothrow;

This just doesn't make sense to me. You emphasized "might" which implies you have no use case in mind and I cannot imagine one.

> Above I provide the default because I have to (direction does
> not have the
> def. ctor). However, I still *might* like to throw on failure.

That's an interesting use case. An interface that takes a non-const reference to the output value would work.

   direction dir(direction::up);
   if (convert(str, dir)) ...

The arguments could occur in either order, of course, and I normally put output parameters first, but thought the order shown fit the usual reading of "convert a to b" of such an expression. That could be spelled other ways, too, like, "convert(str).to(dir)."

That approach is also like what I have been advocating to avoid implicit output conversions.

> BTW, what do you think of
>
> convert<string, int>(s) & boost::dothrow;
>
> instead of
>
> convert<string, int>(s) >> boost::throw_t();
>
> People seem to get put off by op>>.

I don't think either is needed. One interface should imply an exception and another, with a default value, should imply no exception. If forced to choose, I'd say neither as, again, operator |() makes more sense:

   convert<int>(str) | boost::throw;

_____
Rob Stewart robert.stewart_at_[hidden]
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.


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