[convert] no-throw and fallback feature

Hi, I was thinking on the fallback feature a little bit more and I've the impression that we can get it for free. If we accept that we need a no-throw function such as try_convert_to that returns an optional Target we can have the fallback using the optional::get_value_or function auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); or just int i = try_convert_to(*int*)(s).get_value_or(fallback); or int i = get_value_or(try_convert_to(*int*)(s), fallback); I don't know if it is worth adding a function that does all in one int i = convert_to_or(*int*)(s, fallback); Best, Vicente

From: "Vicente BOTET" <vicente.botet@wanadoo.fr> Hi,
I was thinking on the fallback feature a little bit more and I've the impression that we can get it for free. If we accept that we need a no-throw function such as try_convert_to that returns an optional Target we can have the fallback using the optional::get_value_or function
auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); ... I don't know if it is worth adding a function that does all in one
int i = convert_to_or(*int*)(s, fallback);
Vicente, Your suggestion of deploying get_value_or() indeed provides the fallback feature quite easily. However, the original 2 args function Target v = convert_to_or<Target>(s, fallback); does that and more. :-) It does not require the Target type to be DefaultConstructible. Something dear to my heart. :-) V.

Message du 08/05/11 12:57 De : "Vladimir Batov" A : boost@lists.boost.org Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
From: "Vicente BOTET" Hi,
I was thinking on the fallback feature a little bit more and I've the impression that we can get it for free. If we accept that we need a no-throw function such as try_convert_to that returns an optional Target we can have the fallback using the optional::get_value_or function
auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); ... I don't know if it is worth adding a function that does all in one
int i = convert_to_or(*int*)(s, fallback);
Vicente,
Your suggestion of deploying get_value_or() indeed provides the fallback feature quite easily. However, the original 2 args function
Target v = convert_to_or(s, fallback);
does that and more. :-) It does not require the Target type to be DefaultConstructible. Something dear to my heart. :-)
You are right, convert_to_or can be specialized for non default constructible types and could even perform better. What others think of the naming and signatures? Best, Vicente

Vicente BOTET wrote:
De : "Vladimir Batov"
From: "Vicente BOTET"
I was thinking on the fallback feature a little bit more and I've the impression that we can get it for free. If we accept that we need a no-throw function such as try_convert_to that returns an optional Target we can have the fallback using the optional::get_value_or function
auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); ...
The issue raised before is that "try" indicates a bool return type. Perhaps "maybe_as" would work? auto o(convert::maybe_as<int>(s)); However, I do like the use of get_value_or().
I don't know if it is worth adding a function that does all in one
int i = convert_to_or(*int*)(s, fallback);
Don't forget the name when in its namespace and with the type specified clearly: convert::convert_to_or<int>(s, fallback). The repetition of "convert" is not ideal, but no different than "convert_cast" and stands up well with a using declaration or directive. Unfortunately, "to_or<int>" isn't right. It suggests something other than int is the desire. I can't think of a good name, so I'm inclined to reject this function. If a better name arises, I can certainly see some value in including such a function, but at some point, there get to be too many ways to do a thing and that, itself, confuses matters. Thus, this function must be considered in light of the entire API. _____ 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.

Message du 09/05/11 17:14 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
De : "Vladimir Batov"
From: "Vicente BOTET"
I was thinking on the fallback feature a little bit more and I've the impression that we can get it for free. If we accept that we need a no-throw function such as try_convert_to that returns an optional Target we can have the fallback using the optional::get_value_or function
auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); ...
The issue raised before is that "try" indicates a bool return type. Perhaps "maybe_as" would work?
auto o(convert::maybe_as(s));
However, I do like the use of get_value_or().
I remember this point. The fact that optional is implicitly convertible to a safe bool let me think that try_ is ok. But if a better name is found I would adopt it. There is something that I like of the function returning optional. But I will first comeback to the prototype that returned a pair Target,bool. As a pair is considered as a tuple we can write tie(i,b) = convert_to(s); the main problem of this prototype is that target must be copied and a default value is needed when the conversion fails. If we see optional as a kind of conditional tuple and we imagine something like a conditional tie (let me call it 'ctie'), we could be able to write ctie(i,b) = try_convert_to(s); We could also write, if (ctie(i,b) = try_convert_to(s),b ) .... If in addition the result of ctie is implicitly convertible to bool, we can have if ((ctie(i,b) = try_convert_to(s)) ... Sorry for the digression.
I don't know if it is worth adding a function that does all in one
int i = convert_to_or(*int*)(s, fallback);
Don't forget the name when in its namespace and with the type specified clearly: convert::convert_to_or(s, fallback). The repetition of "convert" is not ideal, but no different than "convert_cast" and stands up well with a using declaration or directive. Unfortunately, "to_or" isn't right. It suggests something other than int is the desire.
Boost.Conversion defines all these operations at the boost namespace level, as it is done for the other generic cast, lexical_cast, numeric_cast, polymorphic_cast, ... I agree that we should use as specific namespace for each library, but we the operations are generic it is IMO desirable that these functions stay on the boost namespace. If I was forced to add a namespace I will of course choose conversion.
I can't think of a good name, so I'm inclined to reject this function. If a better name arises, I can certainly see some value in including such a function, but at some point, there get to be too many ways to do a thing and that, itself, confuses matters. Thus, this function must be considered in light of the entire API.
I like convert_to_or, I don't think it is absolutely needed, but it could be added without too much noise. Best, Vicente

Vicente BOTET wrote:
De : "Stewart, Robert"
Vicente BOTET wrote:
De : "Vladimir Batov"
From: "Vicente BOTET"
auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); ...
The issue raised before is that "try" indicates a bool return type. Perhaps "maybe_as" would work?
auto o(convert::maybe_as(s));
However, I do like the use of get_value_or().
I remember this point. The fact that optional is implicitly convertible to a safe bool let me think that try_ is ok.
Perhaps so.
There is something that I like of the function returning optional.
get_value_or() makes it useful nice. optional has good semantics for what we're trying to do. The safe-bool conversion is not unreasonable, but it does suffer from the implicit conversion issue WRT template type deduction.
But I will first comeback to the prototype that returned a pair Target,bool. As a pair is considered as a tuple we can write
tie(i,b) = convert_to(s);
I thought about that briefly at one point in the discussions.
the main problem of this prototype is that target must be copied and a default value is needed when the conversion fails.
The extra copy is not desirable when there are reasonable (or, at least, not unreasonable) alternatives to avoid it.
If we see optional as a kind of conditional tuple and we imagine something like a conditional tie (let me call it 'ctie'), we could be able to write
ctie(i,b) = try_convert_to(s);
I presume that no assignment would be done to i if b is false. That actually means writing this: int i; bool b; ctie(i, b) = try_converting_to<int>(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; } Compare that to this: int i(fallback); if (!try_converting_to<int>(s, i)) { std::cerr << "using fallback\n"; } The optional returning version provides useful benefits like no extra copy, get_value_or(), and no instance of the target type if the conversion fails.
We could also write,
if (ctie(i,b) = try_convert_to(s),b ) ....
If in addition the result of ctie is implicitly convertible to bool, we can have
if ((ctie(i,b) = try_convert_to(s)) ...
Interesting, but probably too much of a good thing. Besides, the same thing is done with the following which is simpler and less tricky: int i; if (try_converting_to<int>(s, i)) ...
int i = convert_to_or(*int*)(s, fallback);
Don't forget the name when in its namespace and with the type specified clearly: convert::convert_to_or(s, fallback). The repetition of "convert" is not ideal, but no different than "convert_cast" and stands up well with a using declaration or directive. Unfortunately, "to_or" isn't right. It suggests something other than int is the desire.
Boost.Conversion defines all these operations at the boost namespace level, as it is done for the other generic cast, lexical_cast, numeric_cast, polymorphic_cast, ...
Current policy is to put nothing directly into the boost namespace. Perhaps that can be relaxed, but don't count on it.
I agree that we should use as specific namespace for each library, but we the operations are generic it is IMO desirable that these functions stay on the boost namespace. If I was forced to add a namespace I will of course choose conversion.
You don't think "convert" is a good choice?
I can't think of a good name, so I'm inclined to reject this function. If a better name arises, I can certainly see some value in including such a function, but at some point, there get to be too many ways to do a thing and that, itself, confuses matters. Thus, this function must be considered in light of the entire API.
I like convert_to_or, I don't think it is absolutely needed, but it could be added without too much noise.
Do you mean you like the name, in contrast to my argument against it above, or that you like the function? _____ 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.

Message du 09/05/11 21:07 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
De : "Stewart, Robert"
Vicente BOTET wrote:
De : "Vladimir Batov"
From: "Vicente BOTET"
auto r = try_convert_to(*int*)(s); int i = r.get_value_or(fallback); ...
The issue raised before is that "try" indicates a bool return type. Perhaps "maybe_as" would work?
auto o(convert::maybe_as(s));
However, I do like the use of get_value_or().
I remember this point. The fact that optional is implicitly convertible to a safe bool let me think that try_ is ok.
Perhaps so.
There is something that I like of the function returning optional.
get_value_or() makes it useful nice. optional has good semantics for what we're trying to do. The safe-bool conversion is not unreasonable, but it does suffer from the implicit conversion issue WRT template type deduction.
But I will first comeback to the prototype that returned a pair Target,bool. As a pair is considered as a tuple we can write
tie(i,b) = convert_to(s);
I thought about that briefly at one point in the discussions.
the main problem of this prototype is that target must be copied and a default value is needed when the conversion fails.
The extra copy is not desirable when there are reasonable (or, at least, not unreasonable) alternatives to avoid it.
If we see optional as a kind of conditional tuple and we imagine something like a conditional tie (let me call it 'ctie'), we could be able to write
ctie(i,b) = try_convert_to(s);
I presume that no assignment would be done to i if b is false.
That actually means writing this:
int i; bool b; ctie(i, b) = try_converting_to(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
Compare that to this:
int i(fallback); if (!try_converting_to(s, i)) { std::cerr << "using fallback\n"; }
The optional returning version provides useful benefits like no extra copy, get_value_or(), and no instance of the target type if the conversion fails.
We could also write,
if (ctie(i,b) = try_convert_to(s),b ) ....
If in addition the result of ctie is implicitly convertible to bool, we can have
if ((ctie(i,b) = try_convert_to(s)) ...
Interesting, but probably too much of a good thing.
Besides, the same thing is done with the following which is simpler and less tricky:
int i; if (try_converting_to(s, i)) ...
int i = convert_to_or(*int*)(s, fallback);
Don't forget the name when in its namespace and with the type specified clearly: convert::convert_to_or(s, fallback). The repetition of "convert" is not ideal, but no different than "convert_cast" and stands up well with a using declaration or directive. Unfortunately, "to_or" isn't right. It suggests something other than int is the desire.
Boost.Conversion defines all these operations at the boost namespace level, as it is done for the other generic cast, lexical_cast, numeric_cast, polymorphic_cast, ...
Current policy is to put nothing directly into the boost namespace. Perhaps that can be relaxed, but don't count on it.
I know that the policy is to try to avoid it. I will add a namespace for Boost.Conversion to avoid discussing on this subject, but I really think that in this case it is better to don't use a specific namespace.
I agree that we should use as specific namespace for each library, but we the operations are generic it is IMO desirable that these functions stay on the boost namespace. If I was forced to add a namespace I will of course choose conversion.
You don't think "convert" is a good choice?
I would prefer to use a noun for namespace, then an adjetive and in the last instance a meaningless name, like spirit. I have never used a verb as namespace. The same applies to classes. For me convert stands for a function, converter for a class, convertible for an interface and conversion for a namespace. I'm sure you agree with me on this common usage.
I can't think of a good name, so I'm inclined to reject this function. If a better name arises, I can certainly see some value in including such a function, but at some point, there get to be too many ways to do a thing and that, itself, confuses matters. Thus, this function must be considered in light of the entire API.
I like convert_to_or, I don't think it is absolutely needed, but it could be added without too much noise.
Do you mean you like the name, in contrast to my argument against it above, or that you like the function?
The name. boost::convert_to_or() or boost::conversion::convert_to_or() are good for me. Best, Vicente

Vicente BOTET wrote:
De : "Stewart, Robert"
You don't think "convert" is a good choice?
I would prefer to use a noun for namespace, then an adjetive and in the last instance a meaningless name, like spirit. I have never used a verb as namespace.
That's a good policy. My only argument in favor of "convert" is that it works so well for things like convert::to (and it's shorter!).
The same applies to classes. For me convert stands for a function, converter for a class, convertible for an interface and conversion for a namespace. I'm sure you agree with me on this common usage.
Yes, certainly.
The name. boost::convert_to_or() or boost::conversion::convert_to_or() are good for me.
Well, I'll just reiterate that convert_to_or<int>(s, i) reads wrong to me. I see the possibility that "to" goes with "<int>" and "or" with "i," but that's just too unusual. _____ 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 5/9/2011 2:58 PM, Stewart, Robert wrote:
Vicente BOTET wrote:
De : "Stewart, Robert"
You don't think "convert" is a good choice?
I would prefer to use a noun for namespace, then an adjetive and in the last instance a meaningless name, like spirit. I have never used a verb as namespace.
That's a good policy. My only argument in favor of "convert" is that it works so well for things like convert::to (and it's shorter!).
The same applies to classes. For me convert stands for a function, converter for a class, convertible for an interface and conversion for a namespace. I'm sure you agree with me on this common usage.
Yes, certainly.
If there will be short names like "to" or "as" in the namespace then namespace qualification in user code will practically be necessary. So 'convert' would look much better in that case. But I'm not a fan of the short names and would rather do: namespace bcv = boost::conversion; bcv::convert_to<int>("42"); On the other hand, 'convert' is both a noun and a verb. :P
The name. boost::convert_to_or() or boost::conversion::convert_to_or() are good for me.
Well, I'll just reiterate that convert_to_or<int>(s, i) reads wrong to me. I see the possibility that "to" goes with "<int>" and "or" with "i," but that's just too unusual.
I agree with Rob; the word "or" is a bad way to end an identifier. -Matt

Matthew Chambers wrote:
On 5/9/2011 2:58 PM, Stewart, Robert wrote:
Vicente BOTET wrote:
De : "Stewart, Robert"
You don't think "convert" is a good choice?
I would prefer to use a noun for namespace, then an adjetive and in the last instance a meaningless name, like spirit. I have never used a verb as namespace.
That's a good policy. My only argument in favor of "convert" is that it works so well for things like convert::to (and it's shorter!).
If there will be short names like "to" or "as" in the namespace then namespace qualification in user code will practically be necessary.
I'd use to<int>(s) or as<int>(s) without qualification.
On the other hand, 'convert' is both a noun and a verb. :P
:) Too bad they don't both have the same pronunciation! _____ 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.

From: "Stewart, Robert" <Robert.Stewart@sig.com>
Vicente BOTET wrote:
The same applies to classes. For me convert stands for a function, converter for a class, convertible for an interface and conversion for a namespace. I'm sure you agree with me on this common usage.
Yes, certainly.
Conventions are good as far as they serve a purpose. Blindly following anything (a particular convention in this case) is questionable. The distinction between classes and functions is quite blurred IMO. Do I need to mention a functor? In the end, the user does not give a hoot about any particular conventions the author might have been following as long as the resulting code is clean/easy to read. With that in mind it's hard to beat boost::convert::to<int>. Anything else mentioned so far (like boost::conversion::convert_to, etc.) seem inferior to me (your mileage may vary). V.

Message du 09/05/11 21:07 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
But I will first comeback to the prototype that returned a pair Target,bool. As a pair is considered as a tuple we can write
tie(i,b) = convert_to(s);
I thought about that briefly at one point in the discussions.
the main problem of this prototype is that target must be copied and a default value is needed when the conversion fails.
The extra copy is not desirable when there are reasonable (or, at least, not unreasonable) alternatives to avoid it.
I agree.
If we see optional as a kind of conditional tuple and we imagine something like a conditional tie (let me call it 'ctie'), we could be able to write
ctie(i,b) = try_convert_to(s);
ctie will left i unchanged if b is true.
I presume that no assignment would be done to i if b is false.
That actually means writing this:
int i; bool b; ctie(i, b) = try_converting_to(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
Compare that to this:
int i(fallback); if (!try_converting_to(s, i)) { std::cerr << "using fallback\n"; }
The optional returning version provides useful benefits like no extra copy, get_value_or(), and no instance of the target type if the conversion fails.
The fist is more on the line of functional paradigm. The second on the procedural one. I understand that the procedural one can be more efficient, but the functional one separates clearly what are the in a,d the out parameters. Are both alternatives exclusive?
We could also write,
if (ctie(i,b) = try_convert_to(s),b ) ....
If in addition the result of ctie is implicitly convertible to bool, we can have
if ((ctie(i,b) = try_convert_to(s)) ...
Interesting, but probably too much of a good thing.
I agree, as most of us are not used to use tie, which is really convenient in a lot of cases. tie allows to avoid the use of first and second field of a pair in a clear way. Once we are familiar with tie, ctie is less surprising to me. A better name for ctie could be opt_tie.
Besides, the same thing is done with the following which is simpler and less tricky:
int i; if (try_converting_to(s, i)) ...
If conversion to bool is implicit the bool parameter will be redundant and the preceding could be expressed as int i; if ((opt_tie(i) = try_convert_to(*int*)(s))) ... which is not so bad. Best, Vicente

Vicente BOTET wrote:
De : "Stewart, Robert"
Vicente BOTET wrote:
If we see optional as a kind of conditional tuple and we imagine something like a conditional tie (let me call it 'ctie'), we could be able to write
ctie(i,b) = try_convert_to(s);
ctie will left i unchanged if b is true.
ctie won't change i if the conversion succeeds?
I presume that no assignment would be done to i if b is false.
Surely that is the right interpretation.
That actually means writing this:
int i; bool b; ctie(i, b) = try_converting_to(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
Compare that to this:
int i(fallback); if (!try_converting_to(s, i)) { std::cerr << "using fallback\n"; }
The fist is more on the line of functional paradigm. The second on the procedural one. I understand that the procedural one can be more efficient, but the functional one separates clearly what are the in a,d the out parameters. Are both alternatives exclusive?
They aren't exclusive, but they'd need different names and, again, I suspect we'd be getting into the too-many-choices conundrum.
Besides, the same thing is done with the following which is simpler and less tricky:
int i; if (try_converting_to(s, i)) ...
If conversion to bool is implicit the bool parameter will be redundant and the preceding could be expressed as
int i; if ((opt_tie(i) = try_convert_to(*int*)(s))) ...
Ah, right. That's a curious approach to it. You're suggesting, if I have all the parts aligned right, that try_convert_to() return optional<T> and that opt_tie() assign to its argument iff the optional is set. That means there's an optional-based API and the following is also possible: int i(fallback); opt_tie(i) = try_convert_to<int>(s); _____ 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.

Message du 09/05/11 23:40 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
De : "Stewart, Robert"
Vicente BOTET wrote:
If we see optional as a kind of conditional tuple and we imagine something like a conditional tie (let me call it 'ctie'), we could be able to write
ctie(i,b) = try_convert_to(s);
ctie will left i unchanged if b is true.
if b is false.
ctie won't change i if the conversion succeeds?
I presume that no assignment would be done to i if b is false.
Surely that is the right interpretation.
Yes.
That actually means writing this:
int i; bool b; ctie(i, b) = try_converting_to(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
Compare that to this:
int i(fallback); if (!try_converting_to(s, i)) { std::cerr << "using fallback\n"; }
The fist is more on the line of functional paradigm. The second on the procedural one. I understand that the procedural one can be more efficient, but the functional one separates clearly what are the in a,d the out parameters. Are both alternatives exclusive?
They aren't exclusive, but they'd need different names and, again, I suspect we'd be getting into the too-many-choices conundrum.
Couldn't overload be used here?
Besides, the same thing is done with the following which is simpler and less tricky:
int i; if (try_converting_to(s, i)) ...
If conversion to bool is implicit the bool parameter will be redundant and the preceding could be expressed as
int i; if ((opt_tie(i) = try_convert_to(*int*)(s))) ...
Ah, right. That's a curious approach to it. You're suggesting, if I have all the parts aligned right, that try_convert_to() return optional and that opt_tie() assign to its argument iff the optional is set. That means there's an optional-based API and the following is also possible:
int i(fallback); opt_tie(i) = try_convert_to(s);
Yes this something I could use. Best, Vicente

Vicente BOTET wrote:
De : "Stewart, Robert"
Vicente BOTET wrote:
De : "Stewart, Robert"
int i; bool b; ctie(i, b) = try_converting_to<int>(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
Compare that to this:
int i(fallback); if (!try_converting_to(s, i)) { std::cerr << "using fallback\n"; }
The fist is more on the line of functional paradigm. The second on the procedural one. I understand that the procedural one can be more efficient, but the functional one separates clearly what are the in a,d the out parameters. Are both alternatives exclusive?
They aren't exclusive, but they'd need different names and, again, I suspect we'd be getting into the too-many-choices conundrum.
Couldn't overload be used here?
It could. However, there are two issues. First, note that the second doesn't require the target type template parameter because of the second argument. Second, we're back to the discussion that a "try_" function not returning bool. You've noted that optional offers the safe-bool implicit conversion, of course, but these issues will probably cause concern if not confusion. Recall that the optional returning version can be written as convert_cast<optional<int>>(s) (or convert_to<optional<int>>(s)). Doing so is clear, works nicely with auto, and avoids the issues with a non-bool return value and difference in template parameter treatment. Consequently, I think that's a superior approach.
Besides, the same thing is done with the following which is simpler and less tricky:
int i; if (try_converting_to(s, i)) ...
If conversion to bool is implicit the bool parameter will be redundant and the preceding could be expressed as
int i; if ((opt_tie(i) = try_convert_to(*int*)(s))) ...
Ah, right. That's a curious approach to it. You're suggesting, if I have all the parts aligned right, that try_convert_to() return optional and that opt_tie() assign to its argument iff the optional is set. That means there's an optional-based API and the following is also possible:
int i(fallback); opt_tie(i) = try_convert_to(s);
Yes this something I could use.
Note that such a function need not be named "try_convert_to." I'm not sure what other name to give it, at present, but it would be useful either way. It appears that we're suggesting that opt_tie() be overloaded: int i; bool b; opt_tie(i, b) = convert_to<optional<int>>(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; } and i = fallback; opt_tie(i) = convert_to<optional<int>>(s); Note that it seems to me that opt_tie() should be part of Boost.Optional. For completeness, here's code making the optional explicit and showing the overload: optional<int> o(convert_to<optional<int>>(s)); if (!o) { o = fallback; } if (!try_convert_to(s, i)) { i = fallback; } (I haven't given up on "convert_cast" but I know you prefer "convert_to.") _____ 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.

Message du 10/05/11 13:02 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
De : "Stewart, Robert"
Vicente BOTET wrote:
De : "Stewart, Robert"
int i; bool b; ctie(i, b) = try_converting_to(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
Compare that to this:
int i(fallback); if (!try_converting_to(s, i)) { std::cerr << "using fallback\n"; }
The fist is more on the line of functional paradigm. The second on the procedural one. I understand that the procedural one can be more efficient, but the functional one separates clearly what are the in a,d the out parameters. Are both alternatives exclusive?
They aren't exclusive, but they'd need different names and, again, I suspect we'd be getting into the too-many-choices conundrum.
Couldn't overload be used here?
It could. However, there are two issues. First, note that the second doesn't require the target type template parameter because of the second argument. Second, we're back to the discussion that a "try_" function not returning bool. You've noted that optional offers the safe-bool implicit conversion, of course, but these issues will probably cause concern if not confusion.
Recall that the optional returning version can be written as convert_cast>(s) (or convert_to>(s)). Doing so is clear, works nicely with auto, and avoids the issues with a non-bool return value and difference in template parameter treatment. Consequently, I think that's a superior approach.
Hmmm. I like the optional specialization. I need to see in the absence of auto how usable is it.
Besides, the same thing is done with the following which is simpler and less tricky:
int i; if (try_converting_to(s, i)) ...
If conversion to bool is implicit the bool parameter will be redundant and the preceding could be expressed as
int i; if ((opt_tie(i) = try_convert_to(*int*)(s))) ...
Ah, right. That's a curious approach to it. You're suggesting, if I have all the parts aligned right, that try_convert_to() return optional and that opt_tie() assign to its argument iff the optional is set. That means there's an optional-based API and the following is also possible:
int i(fallback); opt_tie(i) = try_convert_to(s);
Yes this something I could use.
Note that such a function need not be named "try_convert_to." I'm not sure what other name to give it, at present, but it would be useful either way.
It appears that we're suggesting that opt_tie() be overloaded:
int i; bool b; opt_tie(i, b) = convert_to>(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
and
i = fallback; opt_tie(i) = convert_to>(s);
No. I don't think the overload with the boolean parameter is really useful and it is a little bit confusing to have both.
Note that it seems to me that opt_tie() should be part of Boost.Optional.
Yes, of course. If at the end of this discussion we agree on the usefulness of opt_tie, we could start a new thread or contact the maintainer directly. Best, Vicente

Vicente BOTET wrote:
De : "Stewart, Robert"
It appears that we're suggesting that opt_tie() be overloaded:
int i; bool b; opt_tie(i, b) = convert_to<optional<int>>(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
and
i = fallback; opt_tie(i) = convert_to<optional<int>>(s);
No. I don't think the overload with the boolean parameter is really useful and it is a little bit confusing to have both.
I don't think having both would be confusing. Without the bool overload, there's try_convert_to() or using optional overtly: optional<int> const o(convert_to<optional<int>>(s)); if (o) { // use o.get() } else { // use a fallback value std::cerr << "using fallback\n"; } The opt_tie() bool overload is a bit simpler, don't you think? For general use with optional, I think the opt_tie() overload might be useful. _____ 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.

Message du 10/05/11 19:50 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
De : "Stewart, Robert"
It appears that we're suggesting that opt_tie() be overloaded:
int i; bool b; opt_tie(i, b) = convert_to>(s); if (!b) { i = fallback; std::cerr << "using fallback\n"; }
and
i = fallback; opt_tie(i) = convert_to>(s);
No. I don't think the overload with the boolean parameter is really useful and it is a little bit confusing to have both.
I don't think having both would be confusing.
Without the bool overload, there's try_convert_to() or using optional overtly:
optional const o(convert_to>(s)); if (o) { // use o.get() } else { // use a fallback value std::cerr << "using fallback\n"; }
The opt_tie() bool overload is a bit simpler, don't you think?
For general use with optional, I think the opt_tie() overload might be useful.
Sorry Robert. You lost me. Are you using the word overload instead of conversion? Form which overloads of opt_tie are you talking of? opt_tie(T) and opt_tie(T,bool)? Vicente

Vicente BOTET wrote:
For general use with optional, I think the opt_tie() overload might be useful.
Sorry Robert. You lost me.
I'm sorry. I'll try again.
Are you using the word overload instead of conversion?
No. Compare the following options: // ------------------------ // 1 int i(fallback); optional<int> const o(convert_to<optional<int>>(s)); if (o) { i = *o; } else { std::cerr << "using fallback\n"; } // ------------------------ // 2 int i(fallback); bool b; opt_tie(i, b) = convert_to<optional<int>>(s); if (!b) { std::cerr << "using fallback\n"; } // ------------------------ // 3 (Vladimir dislikes this one) int i(fallback); if (!try_convert_to(s, i)) { std::cerr << "using fallback\n"; } Notice that, for those who dislike try_convert_to(), #2 is nicer than #1. Of course, if reporting the use of the fallback isn't needed, and the fallback isn't expensive to compute, there are these options: // ------------------------ // A int i(fallback); opt_tie(i) = convert_to<optional<int>>(s); // ------------------------ // B int const i(convert_to<optional<int>>(s).get_value_or(fallback)); // ------------------------ // C int i(fallback); try_convert_to(s, i); For those who dislike try_convert_to(), A is a more convenient option than B. Both overloads of opt_tie() are useful. Both assign to their first argument, if the optional is set. The one with the extra argument also sets the optional's state in that argument. That's easy enough to explain and use. _____ 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.

Message du 10/05/11 20:39 De : "Stewart, Robert" A : "'boost@lists.boost.org'" Copie à : Objet : Re: [boost] [convert] no-throw and fallback feature
Vicente BOTET wrote:
For general use with optional, I think the opt_tie() overload might be useful.
Sorry Robert. You lost me.
I'm sorry. I'll try again.
Are you using the word overload instead of conversion?
No.
Compare the following options:
// ------------------------ // 1 int i(fallback); optional const o(convert_to>(s)); if (o) { i = *o; } else { std::cerr << "using fallback\n"; }
// ------------------------ // 2 int i(fallback); bool b; opt_tie(i, b) = convert_to>(s); if (!b) { std::cerr << "using fallback\n"; }
// ------------------------ // 3 (Vladimir dislikes this one) int i(fallback); if (!try_convert_to(s, i)) { std::cerr << "using fallback\n"; }
Notice that, for those who dislike try_convert_to(), #2 is nicer than #1.
Of course, if reporting the use of the fallback isn't needed, and the fallback isn't expensive to compute, there are these options:
// ------------------------ // A int i(fallback); opt_tie(i) = convert_to>(s);
// ------------------------ // B int const i(convert_to>(s).get_value_or(fallback));
// ------------------------ // C int i(fallback); try_convert_to(s, i);
For those who dislike try_convert_to(), A is a more convenient option than B.
Both overloads of opt_tie() are useful. Both assign to their first argument, if the optional is set. The one with the extra argument also sets the optional's state in that argument. That's easy enough to explain and use.
If opt_tie is implicitly convertible to a bool as it is optional
// 2 int i(fallback); bool b; opt_tie(i, b) = convert_to>(s); if (!b) { std::cerr << "using fallback\n"; }
can be written as // 2 b int i(fallback); if (!( opt_tie(i) = convert_to>(s)) ) { std::cerr << "using fallback\n"; } I agree however that //2 could be easier to read. Do you think that opt_tie must be implicitly convertible to bool or not? Best, Vicente

On May 10, 2011, at 3:55 PM, Vicente BOTET wrote:
If opt_tie is implicitly convertible to a bool as it is optional
// 2 int i(fallback); bool b; opt_tie(i, b) = convert_to>(s); if (!b) { std::cerr << "using fallback\n"; }
can be written as
// 2 b int i(fallback); if (!( opt_tie(i) = convert_to>(s)) ) { std::cerr << "using fallback\n"; }
I agree however that //2 could be easier to read. Do you think that opt_tie must be implicitly convertible to bool or not?
I think opt_tie should behave as if it's optional<T>&. I am not sure why one would want to chain assignments in this case, but it should be possible. Unfortunately because optional<T&> wants to rebind its reference it's not possible to do as boost::tie does. So, it's probably a wrapper. This works; I'm not sure if it's optimal: #include <boost/optional.hpp> #include <iostream> using boost::optional; using std::cout; using std::endl; /* // does not work because optional<T&> wants to rebind its reference on assignment template<typename T> optional<T&> opt_tie(T &x) { return optional<T&>(x); } */ template<typename T> class opt_tie_type { T &x_; public: opt_tie_type(T &x) : x_(x) {} const optional<T> operator=(optional<T> const& y) { if(y) x_ = y.get(); return y; } }; template<typename T> opt_tie_type<T> opt_tie(T &x) { return opt_tie_type<T>(x); } int main() { optional<int> has(9), hasnt; int x; if(opt_tie(x) = has) cout << "has " << x << endl; x = 17; if(!(opt_tie(x) = hasnt)) cout << "hasn't " << x << endl; //chained assignment int y; optional<int> opt = opt_tie(y) = has; if(opt) cout << "still has " << opt.get() << endl; return 0; }

Gordon Woodhull wrote:
On May 10, 2011, at 3:55 PM, Vicente BOTET wrote:
I think opt_tie should behave as if it's optional<T>&. I am not sure why one would want to chain assignments in this case, but it should be possible.
If you can't explain why it is needed, I consider that a reason to reject it. Since tie() doesn't work that way, it would be surprising. However, it would permit Vicente's use case: int i(fallback); if (!(opt_tie(i) = convert_to<optional<int>>(s))
Unfortunately because optional<T&> wants to rebind its reference it's not possible to do as boost::tie does.
That is, indeed, unfortunate for this purpose.
So, it's probably a wrapper.
Agreed.
This works; I'm not sure if it's optimal:
#include <boost/optional.hpp> #include <iostream>
using boost::optional; using std::cout; using std::endl;
template<typename T> class opt_tie_type { T &x_; public: opt_tie_type(T &x) : x_(x) {} const optional<T> operator=(optional<T> const& y) {
The return type should be optional<T> const & if not void.
if(y) x_ = y.get(); return y; } };
template<typename T> opt_tie_type<T> opt_tie(T &x) { return opt_tie_type<T>(x); }
I don't think anything more optimal is possible after addressing the return type of the assignment operator. However, a robust implementation will need a PTS for reference types to address the reference-to-reference problem (or use remove_reference). _____ 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 11, 2011, at 7:08 AM, Stewart, Robert wrote:
Also, assignment within a conditional is error prone, so often rejected. An idiom that relies on it, even though not a normal assignment, will likely also be rejected.
I'm very sorry to hear that. I hope not! I guess we should consider what opt_tie(i) == convert_cast<..>(...) would mean. Obviously it would fail in the simple impl I posted. If it did work, it wouldn't buy you anything above constructing an ordinary optional<T>. On May 11, 2011, at 7:46 AM, Stewart, Robert wrote:
Gordon Woodhull wrote:
On May 10, 2011, at 3:55 PM, Vicente BOTET wrote:
I think opt_tie should behave as if it's optional<T>&. I am not sure why one would want to chain assignments in this case, but it should be possible.
If you can't explain why it is needed, I consider that a reason to reject it.
Since tie() doesn't work that way, it would be surprising.
From the user's point of view, tie() does work the same. It returns pair<&,&> which is chain-assignable. I would expect an assignment operator to return something convertable to T, whether that is T& (best), T or T const& (okay).
However, it would permit Vicente's use case:
int i(fallback); if (!(opt_tie(i) = convert_to<optional<int>>(s))
This is the way I would like to deal with fallbacks when I need to know whether it succeeded. It's succinct and I think very clear. It might take a little bit of investigation to understand why it works, but I think it's immediately clear what is supposed to happen. I am not as happy with try_convert_to (I don't like out-parameters if they can be avoided), but I understand that everyone has their own preferences, which might include avoiding assignment within a conditional.
template<typename T> class opt_tie_type { T &x_; public: opt_tie_type(T &x) : x_(x) {} const optional<T> operator=(optional<T> const& y) {
The return type should be optional<T> const & if not void.
Good point on the reference. Certainly not void, that would defeat the purpose.
I don't think anything more optimal is possible after addressing the return type of the assignment operator. However, a robust implementation will need a PTS for reference types to address the reference-to-reference problem (or use remove_reference).
Good point. Thanks. But wait a sec, given that opt_tie_type is a detail of opt_tie(), how is it possible that T is a reference type? Vicente, do you want to propose this for Boost.Optional? And what do you think about the overload with extra bool&? It would require a second opt_tie_type. Cheers, Gordon

Gordon Woodhull wrote:
On May 11, 2011, at 7:08 AM, Stewart, Robert wrote:
Also, assignment within a conditional is error prone, so often rejected. An idiom that relies on it, even though not a normal assignment, will likely also be rejected.
I'm very sorry to hear that. I hope not!
I guess we should consider what opt_tie(i) == convert_cast<..>(...) would mean. Obviously it would fail in the simple impl I posted. If it did work, it wouldn't buy you anything above constructing an ordinary optional<T>.
Equality should not be supported.
On May 11, 2011, at 7:46 AM, Stewart, Robert wrote:
Gordon Woodhull wrote:
On May 10, 2011, at 3:55 PM, Vicente BOTET wrote:
I think opt_tie should behave as if it's optional<T>&. I am not sure why one would want to chain assignments in this case but it should be possible.
If you can't explain why it is needed, I consider that a reason to reject it.
I don't think chained assignments is useful -- you may find a good use case -- but returning bool, to support your try_convert_to()-avoiding usage, would work.
Since tie() doesn't work that way, it would be surprising.
From the user's point of view, tie() does work the same. It returns pair<&,&> which is chain-assignable.
Ah, I see what you mean.
I would expect an assignment operator to return something convertable to T, whether that is T& (best), T or T const& (okay).
To support chaining, the assignment operator must return something non-const. Normally, it must be T & in order that the assignment can be to the object first assigned to. In this case, returning a new object that actually assigns through a reference to the same underlying object is not unreasonable, if unusual.
However, it would permit Vicente's use case:
int i(fallback); if (!(opt_tie(i) = convert_to<optional<int>>(s))
This is the way I would like to deal with fallbacks when I need to know whether it succeeded. It's succinct and I think very clear. It might take a little bit of investigation to understand why it works, but I think it's immediately clear what is supposed to happen.
That looks like so much line noise to me, particularly by comparison to try_convert_to().
I am not as happy with try_convert_to (I don't like out- parameters if they can be avoided), but I understand that everyone has their own preferences, which might include avoiding assignment within a conditional.
Indeed.
template<typename T> class opt_tie_type { T &x_; public: opt_tie_type(T &x) : x_(x) {} const optional<T> operator=(optional<T> const& y) {
The return type should be optional<T> const & if not void.
Good point on the reference. Certainly not void, that would defeat the purpose.
void would not default "the" purpose. It would defeat your purpose desire for chaining. The assignment operator assigns through the reference given to the constructor, so the reason opt_tie() was conceived is satisfied. As noted above, returning bool still would permit your syntax: if (!(opt_tie(i) = convert_cast<optional<int>>(s)))
I don't think anything more optimal is possible after addressing the return type of the assignment operator. However, a robust implementation will need a PTS for reference types to address the reference-to-reference problem (or use remove_reference).
Good point. Thanks. But wait a sec, given that opt_tie_type is a detail of opt_tie(), how is it possible that T is a reference type?
You snipped your opt_tie() implementation, but this should be the same: template <class T> opt_tie_type<T> opt_tie(T & _value) { return opt_tie_type<T>(_value); } T will be deduced as a non-reference type, so you're right, the PTS is not needed. _____ 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.

Vicente BOTET wrote:
If opt_tie is implicitly convertible to a bool as it is optional
// 2 int i(fallback); bool b; opt_tie(i, b) = convert_to<optional<int>>(s); if (!b) { std::cerr << "using fallback\n"; }
can be written as
// 2 b int i(fallback); if (!( opt_tie(i) = convert_to<optional<int>>(s)) ) { std::cerr << "using fallback\n"; }
I agree however that //2 could be easier to read. Do you think that opt_tie must be implicitly convertible to bool or not?
I think, while possible, that's much too "magical" and complicated when compared to this: int i(fallback); if (!try_convert_to(s, i)) { std::cerr << "using fallback\n"; } Also, assignment within a conditional is error prone, so often rejected. An idiom that relies on it, even though not a normal assignment, will likely also be rejected. _____ 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.
participants (5)
-
Gordon Woodhull
-
Matthew Chambers
-
Stewart, Robert
-
Vicente BOTET
-
Vladimir Batov