Report from Mont Tremblant C++ Committee meeting

The C++ Standards Committee met this past week in Mont Tremblant, Quebec, Canada. Many Boosters were present, and Boost continues to get praise and encouragement from non-Boost committee members. The Library Working Group (LWG) is starting serious work on TR2. Initial proposals for several Boost libraries were evaluated: Filesystem : Interested? Yes 17, No 0 Date-Time : Interested? Yes 9, No 0 Range : Want a C++03 version aimed at TR2, but still interested in a version based on new language features (Concepts perhaps?). String-algo : Interested, but concern over interface and choice of functions, generic vs basic_string.5.3 separate proposal numeric_cast<> : Interested? Yes 10, No 0 Interval : Interested? Yes 7, No 4. Concerns about sufficiently large user base to justify standardizing. Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface: Pointer interface. Two ways of doing the same thing. Depends on nullptr - is there a backup plan. Dubious of use of references. "Boost style" Threads : Pursue? Strong yes 9, weak yes 5, weak no 0, strong no 1 Also: minmax and / or algorithm std::minmax_element In favor 13, Not in favor 0 TR2 0 2 1 0 C++0X 1 8 0 0 Kevlin Henney Threads : Ask for fleshed-out proposal? Strong yes 3, weak yes 6, weak no 2, strong no 1 The next C++ Committee meeting will be in Berlin, Germany, the first week of April 2006. The meeting after that will be in Portland, Oregon, US, in October 2006. --Beman

Thanks for posting your report here. I understand why the decision was made not to support wide-character file names in Filesystem (http://www.boost.org/libs/filesystem/doc/faq.htm), but it misses half the point. The implications are only considered in the context of portability of applications, but what about portability of the library? If I want to write a wide-character application that runs only on Windows, I cannot use Filesystem, without sacrificing the ability to open all files with names that are valid to NTFS (other than by guessing which code page to convert from). For this reason, I don't think that Filesystem should be considered for inclusion in TR2. - Keith MacDonald "Beman Dawes" <bdawes@acm.org> wrote in message news:dicgag$3qi$1@sea.gmane.org...
The C++ Standards Committee met this past week in Mont Tremblant, Quebec, Canada. Many Boosters were present, and Boost continues to get praise and encouragement from non-Boost committee members.
The Library Working Group (LWG) is starting serious work on TR2. Initial proposals for several Boost libraries were evaluated:
Filesystem : Interested? Yes 17, No 0 <snip>

"Keith MacDonald" <boost@mailclan.net> wrote in message news:didfkv$dcf$1@sea.gmane.org...
Thanks for posting your report here.
I understand why the decision was made not to support wide-character file names in Filesystem (http://www.boost.org/libs/filesystem/doc/faq.htm), ...
The proposal fully supports wide-character file names. See the i18n branch on CVS. That branch should migrate to the CVS head real soon now. Except for very simple libraries, proposals for standardization often differ from the Boost version. Please read the actual proposals rather than assuming they are exactly the same as the Boost versions. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ --Beman

On Mon, 10 Oct 2005 07:21:36 -0400, Beman Dawes wrote
"Keith MacDonald" <boost@mailclan.net> wrote in message news:didfkv$dcf$1@sea.gmane.org...
Thanks for posting your report here.
I understand why the decision was made not to support wide-character file names in Filesystem (http://www.boost.org/libs/filesystem/doc/faq.htm), ...
The proposal fully supports wide-character file names. See the i18n branch on CVS. That branch should migrate to the CVS head real soon now.
Except for very simple libraries, proposals for standardization often differ from the Boost version. Please read the actual proposals rather than assuming they are exactly the same as the Boost versions. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/
Note that the date-time paper hasn't made it there just yet -- in the meantime you can find it at http://www.crystalclearsoftware.com/libraries/date_time/proposal_v75/date_ti... or http://tinyurl.com/7vr3q Jeff

Hi people, Not only I wasn't there at the mettings but from Thuesday night I was undergoing an emergency gall bladder surgery so I coulnd't even respond the email. But I'm back home now... still recovering but I can sit in front of the notebook :)
numeric_cast<> : Interested? Yes 10, No 0 Excelent!
Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface:
Pointer interface.
It figues. FWIW, I'll stand strong on this part of the interface... though I'm not sure how much my position can affect the final TR2 form.
Two ways of doing the same thing.
Hmm, really? Did they gave examples?
Depends on nullptr - is there a backup plan.
I could have proposed 'none' along Optional, in its own context, but that would duplicate much of nullptr... I didn't see the need for such duplication.
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported? General question: what shall I do from now on? Follow the discussions on comp.std.c++? TIA Fernando Cacciola

On Oct 10, 2005, at 10:36 AM, Fernando Cacciola wrote:
Hi people, Not only I wasn't there at the mettings but from Thuesday night I was undergoing an emergency gall bladder surgery so I coulnd't even respond the email. But I'm back home now... still recovering but I can sit in front of the notebook :)
Wow, I surely hope you recover fast.
Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface:
Pointer interface.
It figues. FWIW, I'll stand strong on this part of the interface... though I'm not sure how much my position can affect the final TR2 form.
Two ways of doing the same thing.
Hmm, really? Did they gave examples?
I believe this refers to the pointer interface plus get().
Depends on nullptr - is there a backup plan.
I could have proposed 'none' along Optional, in its own context, but that would duplicate much of nullptr... I didn't see the need for such duplication.
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported?
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
General question: what shall I do from now on? Follow the discussions on comp.std.c++?
This is a good question, and I can only give an opinion (as opposed to an authoritative answer). You might explore a interface here on boost which did not have the pointer interface, and which dropped reference support. Then perhaps submit a follow on paper reflecting that experience. Said paper may either modify your current proposal, or more fully support it. And of course if you can make it to Berlin that is always a plus. -Howard

Howard Hinnant wrote:
On Oct 10, 2005, at 10:36 AM, Fernando Cacciola wrote:
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported?
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
[...]
You might explore a interface here on boost which did not have the pointer interface, and which dropped reference support. Then perhaps submit a follow on paper reflecting that experience. Said paper may either modify your current proposal, or more fully support it.
I use optional reference but I do not like the way rebinding works. I still insist that it follow the way boost::tuple does it. IMO, the same way with tie, when you need it, you'll really need it. I think it was I who requested for optional references, so let me present my use case: In Spirit, a parser may return an attribute. This attribute should only be constructed on a successful match. Thus, optional<T>. A symbol table is a parser in Spirit. Each symbol has a corresponding data slot. On a successful match, the attribute returned is a reference to the data slot. Thus optional<T&>. Ah, yes, and I will forever be against the pointer interface. Zen of Python: ... There should be one-- and preferably only one --obvious way to do it. ... Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman writes:
Ah, yes, and I will forever be against the pointer interface.
Zen of Python: ... There should be one-- and preferably only one --obvious way to do it. ...
I can quote the whole thing any time of the day, but it hardly justifies the existence of 'get', let alone its "obviousness" ;). -- Aleksey Gurtovoy MetaCommunications Engineering

Aleksey Gurtovoy wrote:
Joel de Guzman writes:
Ah, yes, and I will forever be against the pointer interface.
Zen of Python: ... There should be one-- and preferably only one --obvious way to do it. ...
I can quote the whole thing any time of the day, but it hardly justifies the existence of 'get', let alone its "obviousness" ;).
Ya, hmm, well, get() (and get_pointer()) there in the proposal is a mistake (or else the pointer interface is.. clearly both shouldn't coexist) FWIW, I wrote the 2 proposals in a high rush over one weekend 'cause I had no idea there was a dateline until Thorstten told me about it, just a few days earlier.. There were a couple of loose ends in both of them... as you can see. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Joel de Guzman wrote:
Howard Hinnant wrote:
On Oct 10, 2005, at 10:36 AM, Fernando Cacciola wrote:
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported?
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
[...]
You might explore a interface here on boost which did not have the pointer interface, and which dropped reference support. Then perhaps submit a follow on paper reflecting that experience. Said paper may either modify your current proposal, or more fully support it.
I use optional reference but I do not like the way rebinding works. I still insist that it follow the way boost::tuple does it. IMO, the same way with tie, when you need it, you'll really need it. I think it was I who requested for optional references, so let me present my use case:
In Spirit, a parser may return an attribute. This attribute should only be constructed on a successful match. Thus, optional<T>. A symbol table is a parser in Spirit. Each symbol has a corresponding data slot. On a successful match, the attribute returned is a reference to the data slot. Thus optional<T&>.
Ya, if you use optional<T> generically, chances are T is really a reference, so you do want it to support references. And I don't think we should drop that support because of the rebinding issue since I don't see it as much of an issue.. IMO, is about wrapping the mind around the nature of an "optional reference"... once you do that, the current binding rules just comes naturally IMO. The nature of an optional object is that it can be absent... and when an optional reference is absent, there is not much of a choice about what to do: you just have to bind to the rvalue. Since this expression: opt = ref ; cannot but to bind 'opt' to 'ref' if 'opt' happens to be absent, then IMO it just better do that _always_, no matter if 'opt' is absent or not. The other choice of semantic would be inconsistent and depending on the previous state of 'opt'.
Zen of Python: ... There should be one-- and preferably only one --obvious way to do it. ...
Zen of Boost: (can I invent one in the name of Boost? :) "When in the fog, follow the path of least surprise" Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Joel de Guzman wrote:
Howard Hinnant wrote:
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
[...]
You might explore a interface here on boost which did not have the pointer interface, and which dropped reference support. Then perhaps submit a follow on paper reflecting that experience. Said paper may either modify your current proposal, or more fully support it.
I use optional reference but I do not like the way rebinding works. I still insist that it follow the way boost::tuple does it. IMO, the same way with tie, when you need it, you'll really need it. I think it was I who requested for optional references, so let me present my use case:
In Spirit, a parser may return an attribute. This attribute should only be constructed on a successful match. Thus, optional<T>. A symbol table is a parser in Spirit. Each symbol has a corresponding data slot. On a successful match, the attribute returned is a reference to the data slot. Thus optional<T&>.
Ya, if you use optional<T> generically, chances are T is really a reference, so you do want it to support references. And I don't think we should drop that support because of the rebinding issue since I don't see it as much of an issue.. IMO, is about wrapping the mind around the nature of an "optional reference"... once you do that, the current binding rules just comes naturally IMO.
The nature of an optional object is that it can be absent... and when an optional reference is absent, there is not much of a choice about what to do: you just have to bind to the rvalue.
Since this expression:
opt = ref ;
cannot but to bind 'opt' to 'ref' if 'opt' happens to be absent, then IMO it just better do that _always_, no matter if 'opt' is absent or not. The other choice of semantic would be inconsistent and depending on the previous state of 'opt'.
Again, my main objection is this rebinding thing. I don't care so much about the "pointer interface". It's easy to simply ignore it. My main problem is with this rebinding thing. It's counter intuitive and does not follow the tuple<T&> NOR the variant<T&, nil> sementics. In Spirit-2, I will be needing all three as part of client interface of semantic actions: a >> b --> tuple<A, B> a | b --> variant<A, B> !a --> optional<A> It just so happens that !a is a synonym for: a | eps --> variant<A, nil> !!! DANG !!! !a and a | eps behave differently!!! My opinion is very strong on this. THIS BEHAVIOR IS WRONG! No to special cases. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Hi Joel,
cannot but to bind 'opt' to 'ref' if 'opt' happens to be absent, then IMO it just better do that _always_, no matter if 'opt' is absent or not. The other choice of semantic would be inconsistent and depending on the previous state of 'opt'.
Again, my main objection is this rebinding thing. I don't care so much about the "pointer interface". It's easy to simply ignore it. My main problem is with this rebinding thing. It's counter intuitive and does not follow the tuple<T&>
Which it can't since a tuple<T&> couldn't be referencing nothing.
NOR the variant<T&, nil> sementics.
OK, this is much better analogy.
In Spirit-2, I will be needing all three as part of client interface of semantic actions:
a >> b --> tuple<A, B> a | b --> variant<A, B> !a --> optional<A>
It just so happens that !a is a synonym for:
a | eps --> variant<A, nil> !!! DANG !!!
!a and a | eps behave differently!!!
I don't know what 'eps' is for so I can't follow the equivalence between "!a" and "a|eps" Nevertheless, I can see that if optional<A> MUST be equivalent to variant<A,nil>; _and_ variant<T&,nil> doesn't rebind, then neither should optional<T&>. But to complete the argument we would need to show that (1) optional<A> MUST be equivalent to variant<A,nil> (2) variant<T&,nil> doens't rebind when its current type is T&, while it clearly binds when is nil. (2) is easy since variant<> just wouldn't do anything special, so it just wouldn't rebind. But (1), I'm not sure... How can we _argue_ that it must (or must not) without specific use cases or moral positions? Specifically... wouldn't you find odd that the result of assignment depends on whether the lvalue was previously absent or not? Don't you agree that _most_ people would call _that_ counterintuitive? In the end, one can always resort to variant<A,nil> if that and _exactly_ that is needed.. why should optional<A> be nothing but a thin interface on top of it? The basic fact that 'true' references don't rebind on assignment is because a C++ reference is _intended_ to be really just an alias for an object; but then you can't have an absent alias for an object can you? so we would have to begin again discussing the nature of an optional reference. And once we do, we discover that an optional reference is really just a "lexically more convenient" pointer. In most languages I know of which have any form of "nullable" type, "references" are really equivalent to C++ pointers, and there assignment does rebind. Take .NET nullable<T> for example.
My opinion is very strong on this. THIS BEHAVIOR IS WRONG!
Only if (1) holds. Can you show with a solid argument that (1) _shall_ hold? Best Fernando Cacciola

Fernando Cacciola wrote:
Hi Joel,
I don't know what 'eps' is for so I can't follow the equivalence between "!a" and "a|eps"
eps is an epsilon match: matches the null string.
Nevertheless, I can see that if optional<A> MUST be equivalent to variant<A,nil>; _and_ variant<T&,nil> doesn't rebind, then neither should optional<T&>. But to complete the argument we would need to show that (1) optional<A> MUST be equivalent to variant<A,nil>
Only if (1) holds. Can you show with a solid argument that (1) _shall_ hold?
I thought I just did! Oh my... I'm getting tired with this. I'll just refrain from using optional and just use variant everywhere. The variant interface is more reasonable. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
Fernando Cacciola wrote:
Hi Joel,
I don't know what 'eps' is for so I can't follow the equivalence between "!a" and "a|eps"
eps is an epsilon match: matches the null string.
Nevertheless, I can see that if optional<A> MUST be equivalent to variant<A,nil>; _and_ variant<T&,nil> doesn't rebind, then neither should optional<T&>. But to complete the argument we would need to show that (1) optional<A> MUST be equivalent to variant<A,nil>
Only if (1) holds. Can you show with a solid argument that (1) _shall_ hold?
I thought I just did! Oh my...
Well, I think you shown that the equivalence works in your case. I wonderder if there could be _argued_ strongly that the best possible design ever is for optional<T> to follow _exactly_ the semantics of variant<T,nil> Is not that I disagree with that.. is that I don't feel like simply chanching sides, because then I will have to be arguing not with you but with the guy next door.. I want an argument as solid as possible for whatever decision I made.
I'm getting tired with this.
It could help if you voiced your opinion on the problems posed by your model (that is, that the effect of assignment would depend on the lvalue being absent or not). The only thing I heard from you on this point since I raised it for the first time years ago was "it doesn't look good, right". If this problem had not existed we wouldn't be having this discussion. The only way out I see is to figure out how to weight the problems and cons of each model. Simply restating the cons of one of them isn't enough. Anyway, I'm preparing a post for c.s.cpp so we can continue there. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
It could help if you voiced your opinion on the problems posed by your model (that is, that the effect of assignment would depend on the lvalue being absent or not). The only thing I heard from you on this point since I raised it for the first time years ago was "it doesn't look good, right". If this problem had not existed we wouldn't be having this discussion. The only way out I see is to figure out how to weight the problems and cons of each model. Simply restating the cons of one of them isn't enough.
Well, first of all, let me apologize for my tone and giving up too easily. FWIW, if I recall correctly what I said was more than "it doesn't look good", but I don't recall now. As far as I'm concerned, I always thought that what I was against was (and is) for special handling and special cases. I've always stated that the tuple<T&> behavior should be the model (actually, to be more basic: struct { T& x; } ). The nullability aspect is *besides* the point and has nothing at all to do with the rebinding semantics. I remember saying "when in doubt, do as the structs do. There's definitely some doubt. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
Fernando Cacciola wrote:
It could help if you voiced your opinion on the problems posed by your model (that is, that the effect of assignment would depend on the lvalue being absent or not). The only thing I heard from you on this point since I raised it for the first time years ago was "it doesn't look good, right". If this problem had not existed we wouldn't be having this discussion. The only way out I see is to figure out how to weight the problems and cons of each model. Simply restating the cons of one of them isn't enough.
Well, first of all, let me apologize for my tone and giving up too easily.
np
FWIW, if I recall correctly what I said was more than "it doesn't look good", but I don't recall now.
I'm pretty sure just simply acknowldeged the problem but didn't propose an alternative solution. I need to do it again but, in the past, I went over all of the related discussions twice.
As far as I'm concerned, I always thought that what I was against was (and is) for special handling and special cases.
I'm against special cases too. But when the special handling is, or appears to be, necessary, getting rid of it is quite difficult.
I've always stated that the tuple<T&> behavior should be the model (actually, to be more basic: struct { T& x; } ).
I know, and I always counter-stated that it shouldn't. Tuples can't be emptied. optional<> can; and in fact, nullability is it fundamental characteristic. We can't model optional<> after something that doesn't do the very fundamental thing optional<> does.
The nullability aspect is *besides* the point and has nothing at all to do with the rebinding semantics.
This is 100% false. Is 100% the opposite. Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability. Let me say that again: Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability. So once again, I ask you to deeply consider nullability and the problem it poses on assignment (I hope I don't have to repeat it again), then weight my proposed solution (rebinding) with your expectactions. If possible, propose a better solution or at least show that you don't think the problem is worth a controversial solution like rebinding. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Joel de Guzman wrote:
The nullability aspect is *besides* the point and has nothing at all to do with the rebinding semantics.
This is 100% false. Is 100% the opposite.
Ok, then we're in trouble.
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Let me say that again:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
So once again, I ask you to deeply consider nullability and the problem it poses on assignment (I hope I don't have to repeat it again), then weight my proposed solution (rebinding) with your expectactions. If possible, propose a better solution or at least show that you don't think the problem is worth a controversial solution like rebinding.
I already proposed a solution: no rebinding, no special cases, do as the structs do. Alas, you don't agree that rebinding and nullability are separate concerns. Oh well... To be honest, it's easier for me to simply use variant than to engage in a battle. Perhaps I am looking at the wrong abstraction. Perhaps what I need is a variant and your optional is not really a variant<T, nil>. But then in that case, you should refrain from calling it as such in your documentation. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook. There *is* an alternative design which is a lot simpler and I've been saying that again and again: do as the structs do. It is easier to visualize and understand and ultimately to explain. A more complex design and behavior will surely lead to more gotchas. Keep it as simple as possible. variant<T&, nil> does the right thing. I don't understand why optional can't. Perhaps it's because of the dual pointer interface. But, like Mat Marcus, I also don't buy the pointer model: "Pointers can be null or dereference-able, Optionals can be null or dereferenceable, therefore Optionals are models of Pointers". It seems that Fernando's rationale follows along the lines "Pointers can be null or dereference-able, Optionals can be null or dereferenceable, Pointers can be rebound, therefore Optionals should be rebound-able." Sorry, that does not work for me. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:diphko$tba$1@sea.gmane.org...
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
Here is an interesting thought experiment. What should std::swap do with optional<X &>? In general, swap(x, y) usually has the same effect as the following code, except for perhaps a stronger exception guarantee and faster performance: Foo temp(x); // Step 1. Assume x and y are of type Foo x = y; // Step 2 y = temp; // Step 3 That being the case, what would the following code do? int a = 1; int b = 2; optional<int &> x(a); optional<int &> y(b); swap(x, y); Assume that swap is not specialized for optional, and consider two cases. Case 1: rebind. Step 1 of swap above binds temp to a, step 2 rebinds x to b and step 3 rebinds y to a. Thus the end result is that x and y are each rebound to what the other one was pointing to before. Case 2: no rebind. In this case, Step 1 above binds temp to a as before. But step 2 results in *x = *y, so a is set equal to b and both a and b now equal 2. Then step 3 results in *y = *temp, so b is set equal to a, but since a and b are already equal due to step 1, there results in no change. Thus the end result is that the original value in a is lost. Of course we would specialize swap for optional<T> to call swap(*x, *y) if both x and y are initialized, but I think the fact that this is not equivalent to the unspecialized version is an argument in favor of the rebind semantics. Joe Gottman

Joe Gottman wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:diphko$tba$1@sea.gmane.org...
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
Here is an interesting thought experiment. What should std::swap do with optional<X &>? In general, swap(x, y) usually has the same effect as the following code, except for perhaps a stronger exception guarantee and faster performance: Foo temp(x); // Step 1. Assume x and y are of type Foo x = y; // Step 2 y = temp; // Step 3
That being the case, what would the following code do? int a = 1; int b = 2; optional<int &> x(a); optional<int &> y(b); swap(x, y);
Assume that swap is not specialized for optional, and consider two cases. Case 1: rebind. Step 1 of swap above binds temp to a, step 2 rebinds x to b and step 3 rebinds y to a. Thus the end result is that x and y are each rebound to what the other one was pointing to before.
Case 2: no rebind. In this case, Step 1 above binds temp to a as before. But step 2 results in *x = *y, so a is set equal to b and both a and b now equal 2. Then step 3 results in *y = *temp, so b is set equal to a, but since a and b are already equal due to step 1, there results in no change. Thus the end result is that the original value in a is lost.
Of course we would specialize swap for optional<T> to call swap(*x, *y) if both x and y are initialized, but I think the fact that this is not equivalent to the unspecialized version is an argument in favor of the rebind semantics.
Interesting point! Now consider this: int a = 1; int b = 2; tuple<int&> x(a); tuple<int&> y(b); swap(x, y); What happens after the swap? The same thing happens! before swap a: 1 b: 2 x: 1 y: 2 swap a: 2 b: 2 x: 2 y: 2 Yet, does tuple have to change and assume a rebinding behavior as optional did? Definitely not! (Aside: Keep in mind that we never touched on the nullability of optionals. There's no nulled optional at all anywhere in this thought experiment). At most, I might be inclined to think that boost::reference_wrapper does the right swap and rebind behavior (**): int a = 1; int b = 2; reference_wrapper<int> x(a); reference_wrapper<int> y(b); before swap a: 1 b: 2 x: 1 y: 2 swap a: 1 b: 2 x: 2 y: 1 (**) reference_wrapper rebinds only on explicit copy construction and assignment from another reference_wrapper. Never from assignment from a T (its embedded type). Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

On Oct 14, 2005, at 11:54 PM, Joel de Guzman wrote:
Interesting point! Now consider this:
int a = 1; int b = 2; tuple<int&> x(a); tuple<int&> y(b); swap(x, y);
What happens after the swap? The same thing happens!
before swap a: 1 b: 2 x: 1 y: 2 swap a: 2 b: 2 x: 2 y: 2
It is on my to-do list to propose a specialized swap for tuple, as I just did for pair: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/ n1856.html#20.2.3%20-%20Pairs The effect of the general swap on both pair and tuple are disastrous in the context of move semantics. Consider: typedef pair<int, vector<int> > Pair; Pair x, y; ... swap(x, y); If the general swap is used, this is an O(N) operation, but if instead pair does: swap(x.first, y.first); swap(x.second, y.second); then things just work, O(1). tuple should (will) have an analogous swap (as does tr1::array already - another "tuple like" type). This is already implemented in CodeWarrior Pro 10 (beta). The following: #include <tuple> #include <tupleio> #include <iostream> int main() { int a = 1; int b = 2; std::tr1::tuple<int&> x(a); std::tr1::tuple<int&> y(b); std::cout << "a: " << a << '\n'; std::cout << "b: " << b << '\n'; std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; swap(x, y); std::cout << "swap(x, y)\n"; std::cout << "a: " << a << '\n'; std::cout << "b: " << b << '\n'; std::cout << "x: " << x << '\n'; std::cout << "y: " << y << '\n'; } Outputs: a: 1 b: 2 x: (1) y: (2) swap(x, y) a: 2 b: 1 x: (2) y: (1) So I'm not weighing in on either side of the optional<T&> debate at the moment. All I'm saying is that any argument based on the current behavior of swapping tuple<T&> is going to be false tomorrow (if I can at all influence the committee - and I feel very strongly about this one). -Howard

Howard Hinnant wrote:
On Oct 14, 2005, at 11:54 PM, Joel de Guzman wrote:
[SNIP]
then things just work, O(1). tuple should (will) have an analogous swap (as does tr1::array already - another "tuple like" type). This is already implemented in CodeWarrior Pro 10 (beta). The following:
[SNIP]
So I'm not weighing in on either side of the optional<T&> debate at the moment. All I'm saying is that any argument based on the current behavior of swapping tuple<T&> is going to be false tomorrow (if I can at all influence the committee - and I feel very strongly about this one).
Interesting! Did I missunderstand the example, or your beta implementation of swap() for tr1 tuples rebinds?? TIA -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Joel de Guzman wrote:
Of course we would specialize swap for optional<T> to call swap(*x, *y) if both x and y are initialized, but I think the fact that this is not equivalent to the unspecialized version is an argument in favor of the rebind semantics.
Interesting point!
Very!! This is another problem caused by non-rebinding semantics. Which of course, being a con of non-rebinding, turns into an argument in favor of rebinding.
Now consider this:
int a = 1; int b = 2; tuple<int&> x(a); tuple<int&> y(b); swap(x, y);
What happens after the swap? The same thing happens!
Yet, does tuple have to change and assume a rebinding behavior as optional did? Definitely not!
Why definitely not!?
(Aside: Keep in mind that we never touched on the nullability of optionals. There's no nulled optional at all anywhere in this thought experiment).
Which only means that I have now yet _another_ reason for the rebinding semantics.
At most, I might be inclined to think that boost::reference_wrapper does the right swap and rebind behavior (**):
[SNIP]
(**) reference_wrapper rebinds only on explicit copy construction and assignment from another reference_wrapper. Never from assignment from a T (its embedded type).
(***) Because it doesn't support direct assignment from a T. The cloest match to what optional<> has is: *opt=value which does not rebind, just as reference_wrapper() Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

At 20:28 2005-10-14, Joe Gottman wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:diphko$tba$1@sea.gmane.org...
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
Here is an interesting thought experiment. What should std::swap do with optional<X &>? In general, swap(x, y) usually has the same effect as the following code, except for perhaps a stronger exception guarantee and faster performance: Foo temp(x); // Step 1. Assume x and y are of type Foo x = y; // Step 2 y = temp; // Step 3
That being the case, what would the following code do? int a = 1; int b = 2; optional<int &> x(a); optional<int &> y(b); swap(x, y);
Assume that swap is not specialized for optional, and consider two cases. Case 1: rebind. Step 1 of swap above binds temp to a, step 2 rebinds x to b and step 3 rebinds y to a. Thus the end result is that x and y are each rebound to what the other one was pointing to before.
Case 2: no rebind. In this case, Step 1 above binds temp to a as before. But step 2 results in *x = *y, so a is set equal to b and both a and b now equal 2. Then step 3 results in *y = *temp, so b is set equal to a, but since a and b are already equal due to step 1, there results in no change. Thus the end result is that the original value in a is lost.
Of course we would specialize swap for optional<T> to call swap(*x, *y) if both x and y are initialized, but I think the fact that this is not equivalent to the unspecialized version is an argument in favor of the rebind semantics.
I concur that it's an argument in favor of rebind. On a vaguely related note, I belive that swap semantics haven't been adequately studied. This seems somewhat odd since every computer I've worked on at the instruction level has had a swap (or exchange) instruction. Sometimes it was only registers, others register with memory (a nice atomic test/set instruction, btw) and even a stack machine which would swap the top two elements. Where is this fundamental (it must be fundamental if all the machines implement it) operation in all of our "high level" languages? It's not. Well we add it to the library in C++ (std::swap) but ottherwise ignore it. I came within a fraction (of an inch, millimeter, whatever) of adding an operator (I was going to use :=:) to a Pascal compiler we were implementing for our architecture (of course it had a swap instruction) just to see how it would get used. Alas, the boss said no. Many (well, sci-fi anyhow) stories have been written about "if a word isn't in the language, then the people must not have the concept" (most often referring to the concept of "war"). In C++ "words" (well the verbs) are operators. As we all know, there is no swap operator in C++. People will argue that functions are also words (verbs). Nonetheless, swap is pretty much a poor cousin in this language. I seem to recall a discussion recently about "move" semantics. I didn't read it carefully but what I thought they were driving at was that if one get it working properly some function return (and subsequent (immediate) assignment) implementations would be simplified. I submit that if the problem is to "move" from a temporary location (let's call it ret) to a destination (dest) then: swap(dest, ret); .....and then let ret go "out of scope" more than suffices. A slight nag in the back of my brain says that Feynman's lecture(s?) on computation showed that exchanging information was cost free, it was destroying information that had an energy cost. To say this keeps me awake at night would be an exaggeration, but I still wonder from time to time..... Why can't I swap two references? Why can't I have a standard container of references?
Joe Gottman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

Victor A. Wagner Jr. wrote:
At 20:28 2005-10-14, Joe Gottman wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:diphko$tba$1@sea.gmane.org...
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
Here is an interesting thought experiment. What should std::swap do with optional<X &>? In general, swap(x, y) usually has the same effect as the following code, except for perhaps a stronger exception guarantee and faster performance: Foo temp(x); // Step 1. Assume x and y are of type Foo x = y; // Step 2 y = temp; // Step 3
That being the case, what would the following code do? int a = 1; int b = 2; optional<int &> x(a); optional<int &> y(b); swap(x, y);
Assume that swap is not specialized for optional, and consider two cases. Case 1: rebind. Step 1 of swap above binds temp to a, step 2 rebinds x to b and step 3 rebinds y to a. Thus the end result is that x and y are each rebound to what the other one was pointing to before.
Case 2: no rebind. In this case, Step 1 above binds temp to a as before. But step 2 results in *x = *y, so a is set equal to b and both a and b now equal 2. Then step 3 results in *y = *temp, so b is set equal to a, but since a and b are already equal due to step 1, there results in no change. Thus the end result is that the original value in a is lost.
Of course we would specialize swap for optional<T> to call swap(*x, *y) if both x and y are initialized, but I think the fact that this is not equivalent to the unspecialized version is an argument in favor of the rebind semantics.
I concur that it's an argument in favor of rebind.
Of course not! Have you read my follow up on tuples doing the same? Do you mean that tuple<T&> should also have a rebind semantics because it's not swapping correctly? Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"Victor A. Wagner Jr." <vawjr@rudbek.com> writes: <snip entire message being replied to>
both x and y are initialized, but I think the fact that this is not equivalent to the unspecialized version is an argument in favor of the rebind semantics.
I concur that it's an argument in favor of rebind.
<snip more new content> Title says it all. http://www.boost.org/more/discussion_policy.htm#quoting Thank you. -- Dave Abrahams Boost Moderator

Joel de Guzman <joel@boost-consulting.com> writes:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
There *is* an alternative design which is a lot simpler and I've been saying that again and again: do as the structs do.
I guess you're assuming optional<T&> maps onto a struct with a T& member? That model is not 100% obvious to me. The only way to initialize a plain struct with a reference member is using an initializer list, and the assignment operator for such a struct can't be used. struct X { int& y; }; int z = 3; X x = { z }; X y( x = x ); -- "ComeauTest.c", line 1: error: implicitly generated assignment operator cannot copy: reference member "X::y" struct X { int& y; }; ^ detected during implicit generation of "X &X::operator=(const X &)" at line 5 So "the structs" in this case are never that simple, and they don't provide a guide for what to do with optional<T&>, since the assigment behavior for reference members is always explicitly decided by some class designer.
It is easier to visualize and understand and ultimately to explain. A more complex design and behavior will surely lead to more gotchas.
Seems to me there's plenty of room for confusion in the behavior you want. optional<X&> o; X x; o = x; // Reference bound; no copy ctor called. o = x; // X's copy ctor called
Keep it as simple as possible. variant<T&, nil> does the right thing. I don't understand why optional can't.
Surely it _can_ do the same thing as variant<T&, nil>. It's just not as obvious to everyone that it's the "one true behavior" for optional<T&>. It's not like we're discussing the choice between Emacs and every other editor on the planet ;-)
Perhaps it's because of the dual pointer interface. But, like Mat Marcus, I also don't buy the pointer model: "Pointers can be null or dereference-able, Optionals can be null or dereferenceable, therefore Optionals are models of Pointers".
I don't know if anyone actually made that argument or not, but optionals don't have to be models of Pointers in order to justify the operator*, operator->, and operator safe_bool. The Pointer and Optional concepts could be refinements of some concept that includes nullability and dereferenceability. I'd really like to see a careful and non-judgemental comparison of the two possible design choices, describing the advantages and disadvantages of each one. Until we see something like that, I doubt we will be able to come to a useful consensus. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
But, IMO, it *is* unclear and wordy jargon (http://tinyurl.com/954xg) I find the explanation very difficult to follow. I don't agree that I am being judgemental. IMO, it's important for a model to be as simple as possible. If a certain aspect of a library cannot be explained in clear and concise manner, then that will potentially lead to misinterpretations, loopholes and gotchas later on.
There *is* an alternative design which is a lot simpler and I've been saying that again and again: do as the structs do.
I guess you're assuming optional<T&> maps onto a struct with a T& member? That model is not 100% obvious to me. The only way to initialize a plain struct with a reference member is using an initializer list, and the assignment operator for such a struct can't be used.
[...]
So "the structs" in this case are never that simple, and they don't provide a guide for what to do with optional<T&>, since the assigment behavior for reference members is always explicitly decided by some class designer.
Of course you need an assignment operator... and structs do provide a guide: The point is that you can't rebind it. You can do anything with it, and in the common case, just assign the rhs to the lhs, but you cannot rebind it. That is why I often switch between the "tuple" model, the "variant" model and the "struct" model. Both follow the struct model. And, by the struct model, what I am referring to is the limits on what you can do. Sure you need to have an assignment to a struct to give it sensible semantics. But you can't rebind. That IMO, is the sensible behavior when you are embedding/holding a reference.
I'd really like to see a careful and non-judgemental comparison of the two possible design choices, describing the advantages and disadvantages of each one. Until we see something like that, I doubt we will be able to come to a useful consensus.
Ok. Agreed. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman <joel@boost-consulting.com> writes:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
But, IMO, it *is* unclear and wordy jargon (http://tinyurl.com/954xg) I find the explanation very difficult to follow.
I know what "gobbledegook" means; it's highly pejorative. A link to the explanation in question would be more useful here.
I guess you're assuming optional<T&> maps onto a struct with a T& member? That model is not 100% obvious to me. The only way to initialize a plain struct with a reference member is using an initializer list, and the assignment operator for such a struct can't be used.
[...]
So "the structs" in this case are never that simple, and they don't provide a guide for what to do with optional<T&>, since the assigment behavior for reference members is always explicitly decided by some class designer.
Of course you need an assignment operator... and structs do provide a guide: The point is that you can't rebind it.
You sure can, using nasty tricks. You just destroy the struct in place and re-construct it with the new reference binding.
You can do anything with it, and in the common case, just assign the rhs to the lhs
It's non-obvious to me that it's the common case. Reference members are odd beasts, rarely used in my experience, and I am not sure there's a "usual treatment" for assignment that makes sense. I will agree that the nasty tricks are rarely used and usually best avoided. However, we have at least one example where that was agreed to be best (read the short thread at http://lists.boost.org/Archives/boost/2002/12/41278.php) and of course we have at least one example where rebindability was shown to be the most useful behavior: reference_wrapper itself. Your use case (details unknown to me) seems to speak for the other choice. Recently I brought an issue to the core working group regarding the resolution of DR 103: should when T is int&, should T const& be int const& or simply int& ? Looking at how real use cases for the reference-collapsing rule shake out was an important part of deciding the treatment. So I think it's worth surveying more use cases.
but you cannot rebind it.
That is why I often switch between the "tuple" model, the "variant" model and the "struct" model. Both follow the struct model. And, by the struct model, what I am referring to is the limits on what you can do.
Then shouldn't we prevent assignment altogether? If you are willing to allow a user-defined assignment operator, it can do anything.
Sure you need to have an assignment to a struct to give it sensible semantics. But you can't rebind. That IMO, is the sensible behavior when you are embedding/holding a reference.
I'd really like to see a careful and non-judgemental comparison of the two possible design choices, describing the advantages and disadvantages of each one. Until we see something like that, I doubt we will be able to come to a useful consensus.
Ok. Agreed.
So who will prepare that comparison? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
But, IMO, it *is* unclear and wordy jargon (http://tinyurl.com/954xg) I find the explanation very difficult to follow.
I know what "gobbledegook" means; it's highly pejorative. A link to the explanation in question would be more useful here.
I know that you know what that means. I do not mean to belittle anyone. If that's the case, then I apologize.
Of course you need an assignment operator... and structs do provide a guide: The point is that you can't rebind it.
You sure can, using nasty tricks. You just destroy the struct in place and re-construct it with the new reference binding.
Ah yes, you can do anything in C++.
You can do anything with it, and in the common case, just assign the rhs to the lhs
It's non-obvious to me that it's the common case. Reference members are odd beasts, rarely used in my experience, and I am not sure there's a "usual treatment" for assignment that makes sense. I will agree that the nasty tricks are rarely used and usually best avoided. However, we have at least one example where that was agreed to be best (read the short thread at http://lists.boost.org/Archives/boost/2002/12/41278.php) and of course we have at least one example where rebindability was shown to be the most useful behavior: reference_wrapper itself.
Agreed. After thinking about it for some while, it seems I am being swayed by the reference_wrapper model. If you see my other post regarding the swapability of optional<T&> and tuple<T&>, I seem to be showings signs of concession. I might, on one condition: Allow rebinding *ONLY* on assignment from another optional<T&>. int a = 1; int b = 2; optional<int&> x(a); optional<int&> y(b); x = y; // rebind y = a; // no rebind! assign a to b This BTW is the exact semantics of reference_wrapper. Replace optional<T&> with reference_wrapper<T> and you'll get the same behavior. That said, I still am unsure because this will ultimately open a can of worms for the behavior of tuple<T&> and variant<T&, nil>. Howard Hinnant hinted at a proposal to simply fix swap for tuple. Maybe that's all that's needed. This might be my last post on this issue. Please understand that I mean no offense to anyone. Please understand too that my primary concern is inter-library consistency. As one who have spent quite a bit of time on tuple development, and spent quite a bit of time on using optional references too, and hope to use all three (tuple, optional, variant), I care for consistency in their behavior. If you decide to fix one, then the others should be fixed. I do not buy the argument that optional is different because of its nullability property. In the recent thought experiments, we never touched on null optionals in any way. Sincerely Yours, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
[SNIP]
Agreed. After thinking about it for some while, it seems I am being swayed by the reference_wrapper model. If you see my other post regarding the swapability of optional<T&> and tuple<T&>, I seem to be showings signs of concession. I might, on one condition:
Allow rebinding *ONLY* on assignment from another optional<T&>.
int a = 1; int b = 2; optional<int&> x(a); optional<int&> y(b); x = y; // rebind y = a; // no rebind! assign a to b
Why should direct value assignment be different from assignment? That is, why wouldn't y = a ; be any different from: y = optional<T>(a); ?
That said, I still am unsure because this will ultimately open a can of worms for the behavior of tuple<T&> and variant<T&, nil>.
I've been thiking about variant<T&,nil> and I concluded that it's an unfair comparison. 'nil' there is just a type, it has no special meaning and is totally unrelated to T&. It makes sense for variant<A,B> to follow simple rules becasue variant itself knows nothing about A or B or their relation. But the uninitialized state of optional is not just an additional state. It is a special state. In fact, having a special treatment for that special state is the whole point about optional<>. So to be fair, optional<A> should follow a model more like a subset of variant<A,B,..etc...,NIL> were NIL there were a special type with a special meaning. In that case, the transition from A/B/etc to/from NIL would not have to be as blind and unattended as the transition from A to/from B. I wonder if "A | Nothing" in Haskell is really just exactly like "A | B"...
Howard Hinnant hinted at a proposal to simply fix swap for tuple. Maybe that's all that's needed.
This might be my last post on this issue.
I hope it isn't.
I care for consistency in their behavior. If you decide to fix one, then the others should be fixed.
Why? what's is wrong about them?
do not buy the argument that optional is different because of its nullability property.
But it is. I recentely posted with a sample code snippet why nullability affects the way assignment works if no-rebinding is used.. Tuple and Variant don't show that problem, becasue they are not nullable.
In the recent thought experiments, we never touched on null optionals in any way.
Which hints that rebinding could be needed even in spite of that. But anyway, the only reason why I think is needed is because of nullability. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
But, IMO, it *is* unclear and wordy jargon (http://tinyurl.com/954xg) I find the explanation very difficult to follow.
I know what "gobbledegook" means; it's highly pejorative. A link to the explanation in question would be more useful here.
Oh, I forgot: http://boost.org/libs/optional/doc/optional.html#refassign To this day, I'm still befuddled at the explanation. Then, again, I did not mean to belittle anyone, especially Fernando.
I'd really like to see a careful and non-judgemental comparison of the two possible design choices, describing the advantages and disadvantages of each one. Until we see something like that, I doubt we will be able to come to a useful consensus.
Ok. Agreed.
So who will prepare that comparison?
I'm too biased. I'd rather leave it to someone else to do that. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
Oh, I forgot: http://boost.org/libs/optional/doc/optional.html#refassign
To this day, I'm still befuddled at the explanation.
What's wrong with it? "Rebinding semantics for the assignment of initialized optional references has been chosen to provide consistency among initialization states..." seems pretty clear to me. Since assignment to an uninitialized optional<T&> rebinds, so does assignment to initialized optional<>. Consider the analogy with variant<T&, U&>. What does assignment do? Under the "always rebind" model it rebinds. Under the "behave as a reference" model it depends on the argument type and the current state of the variant. It may assign to the referenced object, or it may rebind. "Always rebind" certainly appears more consistent to the untrained eye.

Peter Dimov wrote:
Joel de Guzman wrote:
Oh, I forgot: http://boost.org/libs/optional/doc/optional.html#refassign
To this day, I'm still befuddled at the explanation.
What's wrong with it?
"Rebinding semantics for the assignment of initialized optional references has been chosen to provide consistency among initialization states..."
There's nothing wrong with that. That's clear. You've snipped out the other parts though. What's not clear is why code like that posted by AlisdairM should assume the behavior: http://lists.boost.org/Archives/boost/2005/10/95487.php A gotcha AFAICT.
seems pretty clear to me. Since assignment to an uninitialized optional<T&> rebinds, so does assignment to initialized optional<>.
Consider the analogy with variant<T&, U&>. What does assignment do? Under the "always rebind" model it rebinds. Under the "behave as a reference" model it depends on the argument type and the current state of the variant. It may assign to the referenced object, or it may rebind.
No. Under the "behave as a reference" model, references should bind only on construction. Everything else is assignment to the referenced object. No rebind.
"Always rebind" certainly appears more consistent to the untrained eye.
Really? To me this is definiteley wrong no matter how you put it: int a = 13; int &b = a; int c = 42; optional< int & > d = b; d = c; // rebind! Ok, this is definitely my last post on the issue. Cheers! -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Joel de Guzman
No. Under the "behave as a reference" model, references should bind only on construction. Everything else is assignment to the referenced object. No rebind.
What happens when the optional is null and there is no referenced object to be assigned to?

Joel de Guzman wrote:
No. Under the "behave as a reference" model, references should bind only on construction. Everything else is assignment to the referenced object. No rebind.
Cool. This eliminates some problematic cases. But now consider variant<X&, Y> v( x ); v = y; // assigns y to x What if Y == nil? Should v = nil(); assign nil() to x?

Joel de Guzman <joel@boost-consulting.com> writes:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
But, IMO, it *is* unclear and wordy jargon (http://tinyurl.com/954xg) I find the explanation very difficult to follow.
I know what "gobbledegook" means; it's highly pejorative. A link to the explanation in question would be more useful here.
Oh, I forgot: http://boost.org/libs/optional/doc/optional.html#refassign
To this day, I'm still befuddled at the explanation.
Except for the last paragraph -- which I agree is confusing but which is also not needed to understand the rationale -- it seems perfectly clear to me. Reasonable, too. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Joel de Guzman wrote:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
But, IMO, it *is* unclear and wordy jargon (http://tinyurl.com/954xg) I find the explanation very difficult to follow.
I wonder what explanation you are referring to? You still haven't addressed the very issue that forms the core of that explanation.
I don't agree that I am being judgemental. IMO, it's important for a model to be as simple as possible. If a certain aspect of a library cannot be explained in clear and concise manner, then that will potentially lead to misinterpretations, loopholes and gotchas later on.
And I totally agree.. But if a design causes misinterpretations, loopholes and gotchas later on, then it might look like being as simple as possible while in reality is over-simplified. Without rebinding semantics, that is, over-simplifying the problem, assignment can do 2 totally different things. That's a source for misinterpretations, loopholes and gotchas.
[SNIP]
Of course you need an assignment operator... and structs do provide a guide: The point is that you can't rebind it.
Yes you can.. you meant you shouldn't.
You can do anything with it, and in the common case, just assign the rhs to the lhs,
What if thre is no rhs to assign to??
but you cannot rebind it. That is why I often switch between the "tuple" model, the "variant" model and the "struct" model. Both follow the struct model. And, by the struct model, what I am referring to is the limits on what you can do. Sure you need to have an assignment to a struct to give it sensible semantics. But you can't rebind. That IMO, is the sensible behavior when you are embedding/holding a reference.
That is a sensible behaviour when embeeding a reference that never references nothing. If your model supports nullability, that is, the reference can reference nothing, then _consistent_ rebinding is a reasonable choice. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

FJoel de Guzman wrote:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model)
FWIW, I never said nor proposed it as a pointer. That was something that people just wronly assumed and keep asumming. All I said, and which I'll keep saying, is that both pointers and optional<> can represent absent objects. But that's not because optional<> is a pointer, is becasue both optional<> and pointer's are somehing else: OptionalPointees.
and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
I can clearly see that you don't recall my rationale. For some reason you just keep failing to see the reasons I have for the rebinding. (the rebinding is built on purpose, for a reason, and not as a side consequence of some design or implementation, so in reality you shouldn't say you don't buy my reasons when I am just stating them)
[SNIP] Keep it as simple as possible. variant<T&, nil> does the right thing. I don't understand why optional can't.
I can see that... So let me explain it once again: If optional<> had NO rebinding. That is, if optional<> were to simply agreegate a reference as you propose, the following would happen: optional<int&> or ; int v = 3 ; int w = 5 ; int x = 10 ; int& rv = v ; int& rw = w ; int& rx = x ; or = rv ; // 'v' is bound for the first time here. or = rw ; // 'or' is initialized so 'v' is changed to 5 [1] or = none ; // back to absent // unlike [1], 'or' is bound now to 'x' rather than 'v' changing its value or = rx ; As you can see, WITHOU REBINDING, in one case of assignment, the value of the referenced object changes, but in the other case of assignment, another object is referenced. I consider this a problem and so I propose rebinding as a way out. Now, anyone reading please understand this: It is the existence of the incosistency above THE ONLY REASON for the rebinding proposal. That incosistency would not exist if it were not because of the nullability of optional<>. Or to avoid a confusion rooted on an undefined term, because of the fact that the lhs can be absent or not, and that affects the semantics of the assignment. Any argument against rebinding _must_ address that problem specifically simply because it is that specific problem alone the reasons for rebinding.
Perhaps it's because of the dual pointer interface.
It has nothing to do with interfaces.
[SNIP] "Pointers can be null or dereference-able, Optionals can be null or dereferenceable, therefore Optionals are models of Pointers". It seems that Fernando's rationale follows along the lines "Pointers can be null or dereference-able, Optionals can be null or dereferenceable,
Pointers can be rebound, therefore Optionals should be rebound-able."
I don't recall anyone saying that last sentence. But in any case, I would disagree with that just as you do. But again, the need for rebinding has nothing to do with pointers. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Stating the obvious, isn't the whole problem because there are two completely separate modes of action during optional reference assignments: 1) Where the reference is assigned (rebinding to references) 2) Where the referred value is assigned (assignments from the underlying type) Pointers do indeed have the same abilities, but they have distinct semantics for these separate modes. I.e. 'p = px' and '*p = *px'. The absence of rebinding of references in c++ is by design not accident. (See p.86 of the Design and Evolution of C++.) IMHO, signalling distinct semantic modes using clear syntax is essential. In the example below, it might not always be clearly that a rebinding has taken place. That requires the programmer to be aware of the types of the variables on both sides of the assignment, and how this could affect what takes place. This behaviour of optional would break the aliasing ability of references, which I feel is deeply ingrained into many c++ (That after "int& ref_AA =AA;" ref_AA can be used exactly in place of AA . Dangerously subtle bugs would be very difficult to find. The easiest solution to disambiguate, would be to force all binding and rebinding of optional references to use distinct syntax (rebind) so that this is clearly signalled at the minor cost of some syntactic verbosity. This means that optional<T&> is no longer completely orthogonal to optional<T> in its syntax, but as that merely reflects the real underlying differences in semantics, this should be an advantage not a disadvantage. Leo Goodstadt
Fernando Cacciola wrote: optional<int&> or ; int v = 3 ; int w = 5 ; int x = 10 ; int& rv = v ; int& rw = w ; int& rx = x ;
or = rv ; // 'v' is bound for the first time here.
or = rw ; // 'or' is initialized so 'v' is changed to 5 [1]
or = none ; // back to absent
// unlike [1], 'or' is bound now to 'x' rather than 'v' changing its value or = rx ;
As you can see, WITHOU REBINDING, in one case of assignment, the value of the referenced object changes, but in the other case of assignment, another object is referenced. I consider this a problem and so I propose rebinding as a way out.

On Behalf Of Leo Goodstadt
The easiest solution to disambiguate, would be to force all binding and rebinding of optional references to use distinct syntax (rebind) so that this is clearly signalled at the minor cost of some syntactic verbosity. This means that optional<T&> is no longer completely orthogonal to optional<T> in its syntax, but as that merely reflects the real underlying differences in semantics, this should be an advantage not a disadvantage.
An easy way to do that would be to disallow optional<T&> and spell it instead as optional<reference_wrapper<T> > as someone suggested the last time this was discussed.

Brock Peabody wrote:
On Behalf Of Leo Goodstadt
The easiest solution to disambiguate, would be to force all binding and rebinding of optional references to use distinct syntax (rebind) so that this is clearly signalled at the minor cost of some syntactic verbosity.
Which is exactly what optional does in the way I proposed it (with rebinding) opt = value ; // always rebinds *opt = *value ; // never rebinds (but is UB if *opt refers to nothing) Notice that the code I posted and where you saw yourself the problem shows the behaviour that would existed if optional<> were not the way I designed it.
This means that optional<T&> is no longer completely orthogonal to optional<T> in its syntax, but as that merely reflects the real underlying differences in semantics, this should be an advantage not a disadvantage.
An easy way to do that would be to disallow optional<T&> and spell it instead as optional<reference_wrapper<T> > as someone suggested the last time this was discussed.
FWIW, optional<T&> has the exact same semantics of optional< reference_wrapper<T> > rebinding on assignment included. NOTE: Don't get distracted by the fact that reference_wrapper<T> istself doesn't rebind on assigment. If _that_ is stored as the value of an optional<>, then _direct_ assignment (opt=val) would always rebind and _indirect_ asssignment (*o=val), would never rebind; just as it is now with my proposed rebinding. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On Behalf Of Fernando Cacciola
Personally, I agree with your choices on rebinding and the "pointer style" interface. The safe_bool idiom is too handy to pass up - it allows you to do nice things like declaring variables in an if expression, and the main reason to overload operator->() is because you can't overload operator.(). Sure it's sugar, but it's tasty and makes life easier.
optional<T&> has the exact same semantics of optional< reference_wrapper<T> >
That's the best description and rationalization of the semantics of optional<T&> I've heard yet.

On Mon, 2005-10-17 at 16:09 -0300, Fernando Cacciola wrote:
But that's not because optional<> is a pointer, is becasue both optional<> and pointer's are somehing else: OptionalPointees.
Let me say first I don't use optional references (yet anyway) and I am quite happy with your explanation of the need to rebind on assignment. I am, however, still not convinced that OptionalPointees is justification for using the interface of a pointer. I still sometimes think of optional as a vector with a maximum size of one, but I now think it would be a bad idea to copy member names from std::vector, as it is likely to cause confusion when using optional< vector< T > >. For the same reason I think optional< bool > is very problematic with the current interface (see my earlier post in this thread). Could the unifying concept OptionalPointee be implemented as free functions? The user could then decide if they want their code to use a pointer, an optional or one of either (and that choice would be obvious to a reader and to the compiler). Something like namespace optional_pointee { template< typename T > inline bool has_value( T * p ) { return p != 0; } template< typename T > inline bool has_value( const optional< T > & o ) { return o.has_value(); } template< typename T > inline T & value( T * p ) { return *p; } template< typename T > inline T & value( const optional< T > & o ) { return o.value(); } } (I know this is an over simplification, as it would need to support smart pointers and optional< T & >) So then you could write... template< typename Pointer > inline void f( Pointer p ) { if( p ) { std::cout << *p; } } or template< typename T > inline void f( const optional< T > & o ) { if( o.has_value() ) { std::cout << o.value(); } } or template< typename OptionalPointee > inline void f( OptionalPointee op ) { if( optional_pointee::has_value( op ) ) { std::cout << optional_pointee::value( op ); } } Though personally I have not yet come across a situation where I want an OptionalPointee as template parameter. Is there some common use that I have overlooked? Hamish

Hi there, Firstly whilst reviewing this thread and the optional docs I spotted a couple of minor typos : "(Re)binds thee wrapped reference." : thee -> the "untitialized" -> uninitialized In the In-place factory discussion, the last code segment has been corrupted slightly : template<class inplacefactory=""></class> should presumably be : template<class InPlaceFactory> Also, whilst the docs I think in general are good, I find some of the acronyms used in the docs slightly too informal for formal documentation, for instance IMO and w.r.t.. Whilst they are well known, it does cause the brain to stall momentarily whilst trying to understand some quite difficult concepts. Now, onto the discussion at hand. I must admit I find the whole rebinding interface very ambiguous. What we have is a reference that is potentially null. In my mind that is a pointer (wrapped up obviously), and not an optional at all. I use a class called ref_ptr<> for that purpose, and it has served me well - A smart pointer with no ownership. That this discussion is going on so long and is so disputed it seems to me that there is no right-way, and the best way of fixing it is to disallow T& altogether. But if it were to stay I would say that the rebinding is very surpising for someone used to using references. Take [1] : int a = 13; int &b = a; int c = 42; optional< int & > d = b; d = c; I just showed the above example to someone else at work. Neither of us have used optional, but have read the docs. We both assumed that a would take on the value of 42, certainly I wouldn't expect it to rebind. In the rationale the first example states "If you assign to an uninitialized optional<T&> the effect is to bind (for the first time) to the object. Clearly, there is no other choice". Actually there is another choice here - Undefined Behaviour. If the following is undefined : optional< int & > o; f(*o); Then it seems perfectly natural to me that this should be undefined as well : int i = 0; optional< int & > o; o = i; Perhaps the problem is the lack of any clue to a dereference on the lhs, in which case make it mandatory for all types. Its quite obvious that this will be undefined : int i = 0; optional< int & > o; *o = i; Remove the operator(const T&) and the ambiguity goes away, you either have int i = 0; optional< int & > o(i); int n = 0; *o = i; // assigns new value o = optional<int&>(i); // rebinds, nice and explicitly Which is what I would expect whether I knew anything about optional or not. Just my tuppence. Sam [1] http://lists.boost.org/Archives/boost/2005/10/95487.php

Sam Partington wrote:
That this discussion is going on so long and is so disputed it seems to me that there is no right-way, and the best way of fixing it is to disallow T& altogether.
That is the direction I am most warming to. T & is does not meet the Copy Constructible requirements of the standard (20.1.3) although const T & comes close. Rather than support it as a special case via rebinding, I am very happy for that special case to be spelled optional< ref< T > > so there is no real loss of functionality, although you need a little more trickery for function templates returning and optional< T > (specialising for the T& case) If simply making the specialization illegal allows us to drop the issue and move forward, that alone makes it worthwhile for me! Optional looks like a great library for TR2, I would hate to see it lose its way in contentious issues. And I doubt the pointer-like interface debate can be so easily swept aside ;?) AlisdairM

Alisdair Meredith wrote:
Sam Partington wrote:
If simply making the specialization illegal allows us to drop the issue and move forward, that alone makes it worthwhile for me!
I won't give up so easity ;) I rather give up direct value assignment which seems to be the real root of the unexpected semantics. I suppose anyone will expect _this_ to rebind: o = optional<int&>(v); And that assignment alone is all that is really needed. The other is just sugar for that.
Optional looks like a great library for TR2, I would hate to see it lose its way in contentious issues.
Me too :-) But I think we can still save the wale, I mean, the reference.
And I doubt the pointer-like interface debate can be so easily swept aside ;?)
Ya, interfaces are the hardest to agree upon. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Sam Partington wrote:
Hi there,
Firstly whilst reviewing this thread and the optional docs I spotted a couple of minor typos :
"(Re)binds thee wrapped reference." : thee -> the "untitialized" -> uninitialized
In the In-place factory discussion, the last code segment has been corrupted slightly : template<class inplacefactory=""></class>
should presumably be :
template<class InPlaceFactory>
Ha, thanks.
Also, whilst the docs I think in general are good, I find some of the acronyms used in the docs slightly too informal for formal documentation, for instance IMO and w.r.t.. Whilst they are well known, it does cause the brain to stall momentarily whilst trying to understand some quite difficult concepts.
OK.
Now, onto the discussion at hand.
I must admit I find the whole rebinding interface very ambiguous.
Just to keep the discussion clear, is a matter of semantics not interface.
What we have is a reference that is potentially null. In my mind that is a pointer (wrapped up obviously), and not an optional at all.
Maybe you meant "not a reference at all"? Well, in optional<> this is implemented as a true reference, not as a pointer like in reference_wrapper(). So is more like that there is a reference or nothing.
I use a class called ref_ptr<> for that purpose, and it has served me well - A smart pointer with no ownership.
That this discussion is going on so long and is so disputed it seems to me that there is no right-way, and the best way of fixing it is to disallow T& altogether.
This is one choice, yes. I hope we can solve it because dorpping T& totally breaks generic programming.
But if it were to stay I would say that the rebinding is very surpising for someone used to using references.
And so is the no-rebinding alternative. Look for _my_ thought experiment in another pos. Do it yourself, show it to your mate, and share with me the results.
In the rationale the first example states "If you assign to an uninitialized optional<T&> the effect is to bind (for the first time) to the object. Clearly, there is no other choice".
[...]
Remove the operator=(const T&)
Yes, this could also work. Initially I was against such operator, but for the wrong reasons, so in the end I accepted it.
int i = 0; optional< int & > o(i); int n = 0; *o = i; // assigns new value o = optional<int&>(i); // rebinds, nice and explicitly
The problem which was raised is that it adds an unnecesary verbosity. That is, why can't you define: o = val ; as a convenient shortcut for: o = optional<T>(val); All by itself, is looks quite reasonable. Now you brought this issue back but into the context of optional references. Is it totally clear to everyone that this rebinds? o = optional<int&>(i); Joel de Guzman said that he wouldn't be against rebinding in this case. He's against rebinding in the direct-assignment case, so simply dropping direct-assignment is definitely a way out, even at the cost of dropping some sugar. One could say: optional does not support a convenient direct assignment operator becasue it could hide the true semantics of the assignment, which are clear if only assignment from another optional is used. (Followed by an example) A related note about the use of operator * You said that, even for optional<T&>, it is clear that this: *o = i; is UB if 'o' is uninitialized. And so there is no problem defining that assignment as really just the assignment of the underlying type, which in the case of optional<T&> doesn't rebind. Now I wonder, if instead of operator*, we used value() (or whatever), would it be just as clear? Consider: int a = 1 ; int b = 2 ; int c = 3 ; int& ra = a ; int& rb = b ; int& rc = c ; optional<int&> o(ra) ; // binds to a // Nullable interface *o = rb ; // assing 'b' to 'a' o = none ; // releases 'a' *o = rc ; // !!! UB !!! Cleary IMO // Container interface o.value() = rb ; // assing 'b' to 'a' o.reset() ; // releases 'a' o.value() = rc ; // !!! Still UB !!! ¿But cleary enough? -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Sam Partington wrote:
In the rationale the first example states "If you assign to an uninitialized optional<T&> the effect is to bind (for the first time) to the object. Clearly, there is no other choice".
[...]
Remove the operator=(const T&)
int i = 0; optional< int & > o(i); int n = 0; *o = i; // assigns new value o = optional<int&>(i); // rebinds, nice and explicitly
The problem which was raised is that it adds an unnecesary verbosity. That is, why can't you define:
o = val ;
as a convenient shortcut for:
o = optional<T>(val);
All by itself, is looks quite reasonable.
Now you brought this issue back but into the context of optional references.
Is it totally clear to everyone that this rebinds?
o = optional<int&>(i);
Joel de Guzman said that he wouldn't be against rebinding in this case. He's against rebinding in the direct-assignment case, so simply dropping direct-assignment is definitely a way out, even at the cost of dropping some sugar. One could say: optional does not support a convenient direct assignment operator becasue it could hide the true semantics of the assignment, which are clear if only assignment from another optional is used. (Followed by an example)
Why not use partial specialization so that optional< T > has the semantic sugar, but optional< T & > does not? Or is this already the case?
A related note about the use of operator *
You said that, even for optional<T&>, it is clear that this:
*o = i;
is UB if 'o' is uninitialized. And so there is no problem defining that assignment as really just the assignment of the underlying type, which in the case of optional<T&> doesn't rebind.
Now I wonder, if instead of operator*, we used value() (or whatever), would it be just as clear?
// Nullable interface
*o = rb ; // assing 'b' to 'a' o = none ; // releases 'a' *o = rc ; // !!! UB !!! Cleary IMO
// Container interface
o.value() = rb ; // assing 'b' to 'a' o.reset() ; // releases 'a' o.value() = rc ; // !!! Still UB !!! ¿But cleary enough?
I personally prefer the nullable interface as it is more intuitive w.r.t. smart pointer usage. o.value() = b reads to me like value() is returning a (temporary) return value, then you are assigning rb to that. Q: If o == none, does *o = foo throw? (I am not familiar with optional<>) On the optional<bool> side, is it posible to provide a specialization for it that doesn't break the optional interface, but still provides the functionality that is wanted from an optional<bool> type as discussed elsewhere? - Reece

Reece Dunn wrote:
Fernando Cacciola wrote:
Sam Partington wrote:
[...]
Why not use partial specialization so that optional< T > has the semantic sugar, but optional< T & > does not? Or is this already the case?
I'm not too fond of template classes that support different interfaces according to the properties of the template parameters. That just doesn't play along with generic programming where the type you optionalize can or cannot be a reference. Think of vector<bool> for instance. I rather keep looking for a consistent solution.
A related note about the use of operator *
You said that, even for optional<T&>, it is clear that this:
*o = i;
is UB if 'o' is uninitialized. And so there is no problem defining that assignment as really just the assignment of the underlying type, which in the case of optional<T&> doesn't rebind.
Now I wonder, if instead of operator*, we used value() (or whatever), would it be just as clear?
// Nullable interface
*o = rb ; // assing 'b' to 'a' o = none ; // releases 'a' *o = rc ; // !!! UB !!! Cleary IMO
// Container interface
o.value() = rb ; // assing 'b' to 'a' o.reset() ; // releases 'a' o.value() = rc ; // !!! Still UB !!! ¿But cleary enough?
I personally prefer the nullable interface as it is more intuitive w.r.t. smart pointer usage. o.value() = b reads to me like value() is returning a (temporary) return value, then you are assigning rb to that.
Me too!
Q: If o == none, does *o = foo throw? (I am not familiar with optional<>)
Yes.. Although strictly speaking is Undefined Behaviour. Depending on the compilation options and your boost setup that can throw or core dump.
optional<bool> side, is it posible to provide a specialization for it that doesn't break the optional interface, but still provides the functionality that is wanted from an optional<bool> type as discussed elsewhere?
Is possible, but I don't like it for the reasons expressed before. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Reece Dunn wrote:
Fernando Cacciola wrote:
Sam Partington wrote:
[...]
Why not use partial specialization so that optional< T > has the semantic sugar, but optional< T & > does not? Or is this already the case?
I'm not too fond of template classes that support different interfaces according to the properties of the template parameters. That just doesn't play along with generic programming where the type you optionalize can or cannot be a reference. Think of vector<bool> for instance. I rather keep looking for a consistent solution.
The difference being that vector<bool> has semantic (but not syntactic) differences, while optional<T&> would have syntactic (but not semantic) differences. And template <class T> optional<T> foo(optional<T> ot) { ... ot = optional<T>(someTexpr); ... } would always work. Just the same as always using iterator_traits<It>::value_type, not It::value_type. Personally, though, I think dropping optional<T&> would be perfectly acceptable. References behave differently to every other built-in type.
A related note about the use of operator *
You said that, even for optional<T&>, it is clear that this:
*o = i;
is UB if 'o' is uninitialized. And so there is no problem defining that assignment as really just the assignment of the underlying type, which in the case of optional<T&> doesn't rebind.
Now I wonder, if instead of operator*, we used value() (or whatever), would it be just as clear?
// Nullable interface
*o = rb ; // assing 'b' to 'a' o = none ; // releases 'a' *o = rc ; // !!! UB !!! Cleary IMO
// Container interface
o.value() = rb ; // assing 'b' to 'a' o.reset() ; // releases 'a' o.value() = rc ; // !!! Still UB !!! �But cleary enough?
I personally prefer the nullable interface as it is more intuitive w.r.t. smart pointer usage. o.value() = b reads to me like value() is returning a (temporary) return value, then you are assigning rb to that.
Me too!
It looks uglier, that's for sure. But that would suggest: int a, b; // set... int& ra = a; int& rb = b; optional<int&> o = ra; // OK, binding *o = rb; // OK, sets a to b o = none; *o = rb; // UB -- attempt to set none with value of rb o = rb; // not UB -- rebind o to b o = ra; // rebind again? o = b; // rebind to refer to b? This is starting to look *exactly* like a pointer, but more confusing. What's the point? (pun intended, unfortunately) Also: template <class A, class B> void foo() { optional<A> oa; optional<B> ob; A a = ...; B b = ...; // then code using any of: oa = b; oa = a; ob = a; ob = b; oa = ob; ob = oa; } foo<int&, int>(); foo<int, int&>(); How is the person who writes that supposed to keep up with what binds to what? [...]

Simon Buchan wrote:
Fernando Cacciola wrote:
Reece Dunn wrote:
Fernando Cacciola wrote:
Sam Partington wrote:
[...]
Why not use partial specialization so that optional< T > has the semantic sugar, but optional< T & > does not? Or is this already the case?
I'm not too fond of template classes that support different interfaces according to the properties of the template parameters. That just doesn't play along with generic programming where the type you optionalize can or cannot be a reference. Think of vector<bool> for instance. I rather keep looking for a consistent solution.
The difference being that vector<bool> has semantic (but not syntactic) differences, while optional<T&> would have syntactic (but not semantic) differences.
Right.. though I'm still reluctant to give references a special syntax.
And
template <class T> optional<T> foo(optional<T> ot) { ... ot = optional<T>(someTexpr); ... }
would always work.
That's why I suggest discarding direct assigment. Is only syntatic sugar.
Personally, though, I think dropping optional<T&> would be perfectly acceptable.
Somewhat acceptable, yes, but I'm still trying to save it. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On 10/18/05, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
I must admit I find the whole rebinding interface very ambiguous. Just to keep the discussion clear, is a matter of semantics not interface.
Yes, but thats just a matter of semantics itself :-) (Of course you're right)
What we have is a reference that is potentially null. In my mind that is a pointer (wrapped up obviously), and not an optional at all.
Maybe you meant "not a reference at all"? Well, in optional<> this is implemented as a true reference, not as a pointer like in reference_wrapper(). So is more like that there is a reference or nothing.
I understand that. What I meant was that in any situation that I might conceivably use an optional<T&> I would use a (wrapped) pointer. It feels like we're trying to find a solution for something that already exists in the language, AND is already well understood by everyone (ie T*). However, I accept your next argument...
That this discussion is going on so long and is so disputed it seems to me that there is no right-way, and the best way of fixing it is to disallow T& altogether.
This is one choice, yes. I hope we can solve it because dorpping T& totally breaks generic programming.
Yes, I can see that this is an important point. But I would like to see an example of where one might do so (I know thats difficult as by its very nature it would be generic).
But if it were to stay I would say that the rebinding is very surpising for someone used to using references.
And so is the no-rebinding alternative. Look for _my_ thought experiment in another pos. Do it yourself, show it to your mate, and share with me the results.
I have done, and that result surprised me too. My point is that if both behaviours lead to surprising results then disambiguate them by making all such operations explicit in their usage, and remove the ambiguous implicit usage. However, it looks like we agree on that, so I won''t go on any more about it.
Is it totally clear to everyone that this rebinds? o = optional<int&>(i);
To me yes absolutely.
Now I wonder, if instead of operator*, we used value() (or whatever), would it be just as clear?
Hmm, I not sure on that one. Personally I like the pointer interface. I have several utility/wrapper classes that use dereference to get at the underlying type, and I'm quite accustomed to the concept/syntaxt. I have no problem with operator* returning a raw reference or a proxy type that will do the assignment itself. But an ordinary function returning a raw reference that might be invalid could be quite unexpected. I guess that depends on whether the pointer interface is agreed upon or not... Sam

Hamish Mackenzie wrote:
On Mon, 2005-10-17 at 16:09 -0300, Fernando Cacciola wrote:
But that's not because optional<> is a pointer, is becasue both optional<> and pointer's are somehing else: OptionalPointees.
Let me say first I don't use optional references (yet anyway) and I am quite happy with your explanation of the need to rebind on assignment.
Good.
I am, however, still not convinced that OptionalPointees is justification for using the interface of a pointer.
OK
I still sometimes think of optional as a vector with a maximum size of one, but I now think it would be a bad idea to copy member names from std::vector, as it is likely to cause confusion when using optional< vector< T > >. For the same reason I think optional< bool > is very problematic with the current interface (see my earlier post in this thread).
The problems with optional<bool> are totally unrelated to the choice of operators * and ->. It is the safe_bool() operator _alone_ which causes that. We can of course discuss whether such operator is worth it given the ambiguity it creates with optional<bool>. That was discussed at length at the time optional<> was reviewed (with me initially opposing safe_bool()), in the end, we agreed that it had more benefits than this simple counter-example.
Could the unifying concept OptionalPointee be implemented as free functions?
Of course. Notice that there are alternatives for safe_bool() that doesn't require dropping * and ->. These alternatives fix the problem with optional<bool>. One example is to simply provide operator !, used like this: if ( !!opt ) is_initialized(); (this is what my initial boost submission did) -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On Tue, 2005-10-18 at 10:50 -0300, Fernando Cacciola wrote:
The problems with optional<bool> are totally unrelated to the choice of operators * and ->.
True and I think if you could fix it you would find it much easier to sell me on using * and ->. The issue I have with * and -> is that they do not make it clear that the type in question is supposed to be an optional (to someone reading the code). I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
It is the safe_bool() operator _alone_ which causes that. We can of course discuss whether such operator is worth it given the ambiguity it creates with optional<bool>. That was discussed at length at the time optional<> was reviewed (with me initially opposing safe_bool()), in the end, we agreed that it had more benefits than this simple counter-example.
I think this problem extends to other types eg. optional< int >. If I have a function template< typename RecordType > void f( const RecordType & r ) { if( !r.some_integer_field() ) { ... } } If the return value of some_integer_field is changed from int to optional< int > will the meaning of the code change without a compiler error? In my experience with optional it is common place to change something from required to being optional and back again.
These alternatives fix the problem with optional<bool>. One example is to simply provide operator !, used like this:
if ( !!opt ) is_initialized();
I don't like this. I don't think it solves the problem just makes it less common (as !bool_value still changes meaning when bool_value is made optional). Was there a problem requiring something like if( opt != null_optional ) is_initialized(); ? Hamish

Hamish Mackenzie <hamish@firestream.co.uk> writes:
On Tue, 2005-10-18 at 10:50 -0300, Fernando Cacciola wrote:
The problems with optional<bool> are totally unrelated to the choice of operators * and ->.
True and I think if you could fix it you would find it much easier to sell me on using * and ->. The issue I have with * and -> is that they do not make it clear that the type in question is supposed to be an optional (to someone reading the code). I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
How about indirect_iterator<std::vector<optional<T> >::iterator> ? -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Tue, 2005-10-18 at 12:43 -0400, David Abrahams wrote:
Hamish Mackenzie <hamish@firestream.co.uk> writes:
True and I think if you could fix it you would find it much easier to sell me on using * and ->. The issue I have with * and -> is that they do not make it clear that the type in question is supposed to be an optional (to someone reading the code). I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
How about
indirect_iterator<std::vector<optional<T> >::iterator>
?
Sold! But now I am worried that I wanted to buy a car (container max size 1) and instead I am getting a the back half of a bicycle (deep copy pointer) welded to the front half of a car. Would I be better off with a bicycle instead? For instance consider template< typename Optional_Pointee > Optional_Pointee add_five( Optional_Pointee x ) { if( x != none ) // Does this work for pointers? { (*x) += 5; } return x; } I imagine if this does not yet work it could be made to. How about... template< typename OptionalPointee, typename Value_Type > Optional_Pointee fill( Optional_Pointee x, Value_Type & default_value ) { if( x == none ) { x = &default_value; // Does this work with optionals? } return x; } To avoid slicing the constructor and assignment operators could be something like... template< typename T > class safe_optional_arg { public: // Support pointers operator T * () const { return source_; } private: explicit safe_optional_arg( T * source ) : source_( source ) { } T * source_; }; template< typename T > inline safe_optional_arg< T > opt( T * source ) { return safe_optional_arg< T >( source ) } class optional { public: optional( safe_option_arg< T > arg ); optional & operator = ( safe_option_arg< T > arg ); }; (would need to support smart pointers too) So that last example would be template< typename OptionalPointee, typename Value_Type > Optional_Pointee fill( Optional_Pointee x, Value_Type & default_value ) { if( x == none ) { x = opt( &default_value ); // fails if default_value would be sliced } return x; } Hamish

Hamish Mackenzie <hamish@firestream.co.uk> writes:
From: Hamish Mackenzie <hamish@firestream.co.uk> Subject: Re: Report from Mont Tremblant C++ Committee meeting Newsgroups: gmane.comp.lib.boost.devel Date: Tue, 18 Oct 2005 23:49:07 +0100 Reply-To: boost@lists.boost.org
On Tue, 2005-10-18 at 12:43 -0400, David Abrahams wrote:
Hamish Mackenzie <hamish@firestream.co.uk> writes:
True and I think if you could fix it you would find it much easier to sell me on using * and ->. The issue I have with * and -> is that they do not make it clear that the type in question is supposed to be an optional (to someone reading the code). I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
How about
indirect_iterator<std::vector<optional<T> >::iterator>
?
Sold!
But now I am worried that I wanted to buy a car (container max size 1) and instead I am getting a the back half of a bicycle (deep copy pointer) welded to the front half of a car. Would I be better off with a bicycle instead?
Whatever. All of these odd cases you pose are distractions from the the fact that having such a common interface can be useful. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Tue, 2005-10-18 at 23:13 -0400, David Abrahams wrote:
Hamish Mackenzie <hamish@firestream.co.uk> writes:
From: Hamish Mackenzie <hamish@firestream.co.uk> Subject: Re: Report from Mont Tremblant C++ Committee meeting Newsgroups: gmane.comp.lib.boost.devel Date: Tue, 18 Oct 2005 23:49:07 +0100 Reply-To: boost@lists.boost.org
On Tue, 2005-10-18 at 12:43 -0400, David Abrahams wrote:
Hamish Mackenzie <hamish@firestream.co.uk> writes:
True and I think if you could fix it you would find it much easier to sell me on using * and ->. The issue I have with * and -> is that they do not make it clear that the type in question is supposed to be an optional (to someone reading the code). I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
How about
indirect_iterator<std::vector<optional<T> >::iterator>
?
Sold!
But now I am worried that I wanted to buy a car (container max size 1) and instead I am getting a the back half of a bicycle (deep copy pointer) welded to the front half of a car. Would I be better off with a bicycle instead?
Whatever. All of these odd cases you pose are distractions from the the fact that having such a common interface can be useful.
I think you may have misunderstood my bad analogy. You have talked me around. Now I am asking for _more_ commonality. Do you think the "fill" example would be useful to fill missing values in vector< OptionalPointee >? Hamish

Hamish Mackenzie <hamish@firestream.co.uk> writes:
On Tue, 2005-10-18 at 23:13 -0400, David Abrahams wrote:
Hamish Mackenzie <hamish@firestream.co.uk> writes:
But now I am worried that I wanted to buy a car (container max size 1) and instead I am getting a the back half of a bicycle (deep copy pointer) welded to the front half of a car. Would I be better off with a bicycle instead?
Whatever. All of these odd cases you pose are distractions from the the fact that having such a common interface can be useful.
I think you may have misunderstood my bad analogy. You have talked me around. Now I am asking for _more_ commonality.
Apologies if I misunderstood.
Do you think the "fill" example would be useful to fill missing values in vector< OptionalPointee >?
Sorry, I don't understand. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Wed, 2005-10-19 at 09:16 -0400, David Abrahams wrote:
Do you think the "fill" example would be useful to fill missing values in vector< OptionalPointee >?
Sorry, I don't understand.
Sorry I was in a hurry and didn't describe what I was thinking better. Here is the example from the other email. template< typename OptionalPointee, typename Value_Type > Optional_Pointee fill( Optional_Pointee x, Value_Type & default_value ) { if( x == none ) { x = &default_value; // Does this work with optionals? } return x; } You might use it like this... std::vector< int * > x1; std::vector< optional< int > > x2; ... int default_value = 5; // I imagine this currently fails due to ( x == none ) std::transform( x1.begin(), x1.end(), x1.begin(), fill( _1, default_value ) ); // And this probably fails due to x = &default_value std::transform( x2.begin(), x2.end(), x2.begin(), fill( _1, default_value ) ); I am not using this as an argument against the use of * and ->. I was just wondering if we could make the above (or something similar) work. Hamish

Hamish Mackenzie wrote:
On Wed, 2005-10-19 at 09:16 -0400, David Abrahams wrote:
Do you think the "fill" example would be useful to fill missing values in vector< OptionalPointee >?
Sorry, I don't understand.
Sorry I was in a hurry and didn't describe what I was thinking better. Here is the example from the other email.
I get your point. You're looking for general usages of the Nullable concept (I won't call it OptionalPointee anymore). I like that.
template< typename OptionalPointee, typename Value_Type > Optional_Pointee fill( Optional_Pointee x, Value_Type & default_value ) { if( x == none ) { x = &default_value; // Does this work with optionals? }
return x; }
No, that doesn't work with optional<>. Furthermore, this is a bad example. In the usage example below, 'x1' would end up with several pointers to the 'default_value' object, while 'x2' would end up with several distinct copies of 'default_value' wrapped inside optional<>. But I like the idea of looking for usefull usages of the Nullable concept. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Hamish Mackenzie wrote:
On Tue, 2005-10-18 at 10:50 -0300, Fernando Cacciola wrote:
The problems with optional<bool> are totally unrelated to the choice of operators * and ->.
True and I think if you could fix it you would find it much easier to sell me on using * and ->. The issue I have with * and -> is that they do not make it clear that the type in question is supposed to be an optional (to someone reading the code).
You mean an object of type optional<> right? Granted. But don't you agree that it makes it clear that the value being accessed could be absent? That is, that the type is nullable (whether as a pointer, an optional, an iterator, etc...) And don't you think that making _that_ clear is more important than making clear that the type is specifically an instance of optional<>?
I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
Dave's just gave one.
It is the safe_bool() operator _alone_ which causes that. We can of course discuss whether such operator is worth it given the ambiguity it creates with optional<bool>. That was discussed at length at the time optional<> was reviewed (with me initially opposing safe_bool()), in the end, we agreed that it had more benefits than this simple counter-example.
I think this problem extends to other types eg. optional< int >. If I have a function
template< typename RecordType > void f( const RecordType & r ) { if( !r.some_integer_field() ) { ... } }
If the return value of some_integer_field is changed from int to optional< int > will the meaning of the code change without a compiler error?
In my experience with optional it is common place to change something from required to being optional and back again.
These alternatives fix the problem with optional<bool>. One example is to simply provide operator !, used like this:
if ( !!opt ) is_initialized();
I don't like this. I don't think it solves the problem just makes it less common (as !bool_value still changes meaning when bool_value is made optional).
OK. Point taken.
Was there a problem requiring something like
if( opt != null_optional ) is_initialized();
Something like that is already supported (opt != none) It's just not the only way to test for absence. In any event, if dropping safe_bool() were a good idea (I'm unsure the bool case worth dropping it), that could be left as the only choice. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On Tue, 2005-10-18 at 15:03 -0300, Fernando Cacciola wrote:
I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
Dave's just gave one.
Indeed and I am convinced. Please read my response to that message though as I had some other questions.
Something like that is already supported (opt != none) It's just not the only way to test for absence. In any event, if dropping safe_bool() were a good idea (I'm unsure the bool case worth dropping it), that could be left as the only choice.
(opt != none) is cool. Does it work for other OptionalPointees too? If not, could it? If the the others stay, the documentation should at least be revised indicate that the problem is not limited to optional< bool >. Even changing from "std::istream &" to "optional< std::istream > &" could easily lead to confusion (boost::tribool won't help much there). For the record I would be against including (opt != 0) for the same reason I don't like the "safe_bool" and "operator !". In fact I don't much care for them existing for any pointers. Using (p != none) or (p != PointersType()) is much more explicit. I think that the likely uses of optional make it more vulnerable than pointers. Thank you for taking the time to address my concerns. Hamish

Hamish Mackenzie wrote:
On Tue, 2005-10-18 at 15:03 -0300, Fernando Cacciola wrote:
I still can't think of an example where it is desirable to have X * and optional< Y > use the same interface.
Dave's just gave one.
Indeed and I am convinced. Please read my response to that message though as I had some other questions.
Something like that is already supported (opt != none) It's just not the only way to test for absence. In any event, if dropping safe_bool() were a good idea (I'm unsure the bool case worth dropping it), that could be left as the only choice.
(opt != none) is cool. Does it work for other OptionalPointees too? If not, could it?
The std optional<> proposal uses "nullptr" which is the typed null pointer constant also proposed for standarization. ( o != nullptr ) would then work with pointers (raw and smart) and optional<> (it would be part of the Nullable concept)
If the the others stay, the documentation should at least be revised indicate that the problem is not limited to optional< bool >. Even changing from "std::istream &" to "optional< std::istream > &" could easily lead to confusion (boost::tribool won't help much there).
Good point.
For the record I would be against including (opt != 0) for the same reason I don't like the "safe_bool" and "operator !". In fact I don't much care for them existing for any pointers.
Indeed. Getting rid of the '0' is the motivation behind nullptr.
Thank you for taking the time to address my concerns.
Thank you for taking the time to post your concerns! -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Hamish Mackenzie wrote:
On Mon, 2005-10-17 at 16:09 -0300, Fernando Cacciola wrote:
But that's not because optional<> is a pointer, is becasue both optional<> and pointer's are somehing else: OptionalPointees.
Let me say first I don't use optional references (yet anyway) and I am quite happy with your explanation of the need to rebind on assignment.
Good.
I am, however, still not convinced that OptionalPointees is justification for using the interface of a pointer.
OK
I still sometimes think of optional as a vector with a maximum size of one, but I now think it would be a bad idea to copy member names from std::vector, as it is likely to cause confusion when using optional< vector< T > >. For the same reason I think optional< bool > is very problematic with the current interface (see my earlier post in this thread).
The problems with optional<bool> are totally unrelated to the choice of operators * and ->. It is the safe_bool() operator _alone_ which causes that. We can of course discuss whether such operator is worth it given the ambiguity it creates with optional<bool>. That was discussed at length at the time optional<> was reviewed (with me initially opposing safe_bool()), in the end, we agreed that it had more benefits than this simple counter-example.
Could the unifying concept OptionalPointee be implemented as free functions?
Of course.
Notice that there are alternatives for safe_bool() that doesn't require dropping * and ->. These alternatives fix the problem with optional<bool>. One example is to simply provide operator !, used like this:
if ( !!opt ) is_initialized();
(this is what my initial boost submission did)
wouldn't requiring nil/none comparison make more sense? optional<bool> opt = ...; if(opt != none) { // is initialized if(opt) { // is true ...; } if(!opt) { // is false ...; } } if(opt == none) { // isn't initialized } Would the single conversion rule apply to: optional<char> oc = next_char(); if(oc == none) // input failed! recover(); if(oc) // optional<char> -> char -> bool ? // not the end of input print(oc);

Simon Buchan wrote:
Fernando Cacciola wrote:
Hamish Mackenzie wrote:
On Mon, 2005-10-17 at 16:09 -0300, Fernando Cacciola wrote:
But that's not because optional<> is a pointer, is becasue both optional<> and pointer's are somehing else: OptionalPointees.
Let me say first I don't use optional references (yet anyway) and I am quite happy with your explanation of the need to rebind on assignment.
Good.
I am, however, still not convinced that OptionalPointees is justification for using the interface of a pointer.
OK
I still sometimes think of optional as a vector with a maximum size of one, but I now think it would be a bad idea to copy member names from std::vector, as it is likely to cause confusion when using optional< vector< T > >. For the same reason I think optional< bool > is very problematic with the current interface (see my earlier post in this thread).
The problems with optional<bool> are totally unrelated to the choice of operators * and ->. It is the safe_bool() operator _alone_ which causes that. We can of course discuss whether such operator is worth it given the ambiguity it creates with optional<bool>. That was discussed at length at the time optional<> was reviewed (with me initially opposing safe_bool()), in the end, we agreed that it had more benefits than this simple counter-example.
Could the unifying concept OptionalPointee be implemented as free functions?
Of course.
Notice that there are alternatives for safe_bool() that doesn't require dropping * and ->. These alternatives fix the problem with optional<bool>. One example is to simply provide operator !, used like this:
if ( !!opt ) is_initialized();
(this is what my initial boost submission did)
wouldn't requiring nil/none comparison make more sense?
More sense than what? safe_bool()? I'm not sure... Beign able to just write if ( o ) or if ( !o ) is too important to let go. optional<> doesn't provide conversion to T so that expression can never refer to the wrapped value, just like that expression on a pointer can never refer to the pointed object.
optional<bool> opt = ...; if(opt != none) { // is initialized if(opt) { // is true ...; } if(!opt) { // is false ...; } } if(opt == none) { // isn't initialized }
Would the single conversion rule apply to: optional<char> oc = next_char(); if(oc == none) // input failed! recover(); if(oc) // optional<char> -> char -> bool ? // not the end of input print(oc);
No. optional<T> cannot be converted (not even explicitely) to T. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On 10/18/05 9:50 AM, "Fernando Cacciola" <fernando_cacciola@hotmail.com> wrote:
Hamish Mackenzie wrote: [SNIP]
Could the unifying concept OptionalPointee be implemented as free functions?
Of course.
Notice that there are alternatives for safe_bool() that doesn't require dropping * and ->. These alternatives fix the problem with optional<bool>. One example is to simply provide operator !, used like this:
if ( !!opt ) is_initialized();
(this is what my initial boost submission did)
I would find having type with an "operator not" but not any Boolean conversion to be a surprise. In fact, I filed a bug for Boost.Rational having this problem. (But I think that case was by accident, not design.) The double-not operator as a workaround for Boolean conversion is an idiom that we should NOT be introducing. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com

Fernando Cacciola wrote:
Joel de Guzman wrote:
[...]
The nullability aspect is *besides* the point and has nothing at all to do with the rebinding semantics.
This is 100% false. Is 100% the opposite.
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Let me say that again:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
So once again, I ask you to deeply consider nullability and the problem it poses on assignment (I hope I don't have to repeat it again), then weight my proposed solution (rebinding) with your expectactions. If possible, propose a better solution or at least show that you don't think the problem is worth a controversial solution like rebinding.
If optional<> is to be useful for references, then it should have the same semantics that a class acting as a proxy-reference has. ie, if I use optional<> with a class like template <typename T> struct Proxy { explicit Proxy(T& obj) : my_obj(&obj) {} Proxy& operator=(T const& obj) { *my_obj = obj; return *this; } // ... T* my_obj; }; then optional<T&> should act as close to optional<proxy<T> > as possible. ie., if optional<T&> does something different just because the template argument is a reference, then there must be a way to replicate that behaviour with optional<proxy<T> > too. As to what behaviour is most useful, I am not sure because I have not yet come across a situation where I wanted an optional<T&> - but I do find the rebinding behaviour surprising. I don't see what nullability per-se has to do with this discussion. Cheers, Ian

On Oct 14, 2005, at 3:01 PM, Ian McCulloch wrote:
Fernando Cacciola wrote:
Joel de Guzman wrote:
[...]
The nullability aspect is *besides* the point and has nothing at all to do with the rebinding semantics.
This is 100% false. Is 100% the opposite.
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Let me say that again:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
So once again, I ask you to deeply consider nullability and the problem it poses on assignment (I hope I don't have to repeat it again), then weight my proposed solution (rebinding) with your expectactions. If possible, propose a better solution or at least show that you don't think the problem is worth a controversial solution like rebinding.
If optional<> is to be useful for references, then it should have the same semantics that a class acting as a proxy-reference has. ie, if I use optional<> with a class like
template <typename T> struct Proxy { explicit Proxy(T& obj) : my_obj(&obj) {}
Proxy& operator=(T const& obj) { *my_obj = obj; return *this; }
// ...
T* my_obj; };
then optional<T&> should act as close to optional<proxy<T> > as possible. ie., if optional<T&> does something different just because the template argument is a reference, then there must be a way to replicate that behaviour with optional<proxy<T> > too. As to what behaviour is most useful, I am not sure because I have not yet come across a situation where I wanted an optional<T&> - but I do find the rebinding behaviour surprising.
I don't see what nullability per-se has to do with this discussion.
I agree with Ian and Joel. I don't see that nullability should be the decisive characteristic. Much more so optional is defined by: In the case that optional holds a value, it should work exactly (or as much as possible) like the type it contains. Rebinding goes counter to that. Best, Jaakko

Jaakko Jarvi wrote:
[...]
I don't see what nullability per-se has to do with this discussion.
I agree with Ian and Joel. I don't see that nullability should be the decisive characteristic.
This is an excrept from the std proposal: http://fcacciola.50webs.com/n1878.htm
>>> Optional references rebind when assigned, that is:
int a = 123 ; int& ra = a ; // ra is bound to a optional<int&> ora = ra ; // ora is bound to a int b = 456 ; int& rb = b ; ora = rb ; // ora is re-bound to rb. This is in sharp contrast with normal C++ references. This decision was made to allow the definition of assignment to be independent of the prior initialization state of the lvalue. If the lvalue optional reference is uninitialized before the assignment there is no choice but to rebind. int a = 123 ; int& ra = a ; // ra is bound to a optional<int&> ora = ra ; // ora is bound to a int b = 456 ; int& rb = b ; ora = nullptr ; // explicitly reset to uninitialized to make the point even more clear. ora = rb ; // ora MUST bind to rb, there is no choice here. Assignment to an initialized optional reference could be made to assign the referenced value, following the behavior of normal C++ references, but then the semantics of assignment would depend on the prior initialization state of the lvalue. The decision, albeit arbitrary, is to rebind." <<<<<<<<<<<<<< You still can't see what nullability has to do with the choice?
Much more so optional is defined by:
In the case that optional holds a value, it should work exactly (or as much as possible) like the type it contains.
Rebinding goes counter to that.
Absolutely. And that's why that kind of statement is not in the std proposal. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Ian McCulloch wrote:
[...]
If optional<> is to be useful for references, then it should have the same semantics that a class acting as a proxy-reference has. ie, if I use optional<> with a class like
template <typename T> struct Proxy { explicit Proxy(T& obj) : my_obj(&obj) {}
Proxy& operator=(T const& obj) { *my_obj = obj; return *this; }
// ...
T* my_obj; };
then optional<T&> should act as close to optional<proxy<T> > as possible.
If optional< proxy<T> > is used, for whatever proxy<T>, you can't assign a value of type T to the optional. You can only assign of value of proxy<T>, so it is the proxy assignment from another proxy, or it's copy ctor, what counts. The proxy assignment from T just won't participate. So the proxy as you've shown here just won't compile in optional<> becasue it has no copy ctor nor assignment from another proxy. The assignment that you wrote there, albeit correct for the proxy<> itself, just won't ever be used if you wrap it into optional<>.
ie., if optional<T&> does something different just because the template argument is a reference
It doesn't. optional<T&> is semantically equivalent to optional<reference_wrapper<T> >
I wanted an optional<T&> - but I do find the rebinding behaviour surprising.
Because you got confused with one additional level of indirection. Go through your example again and look what happens if a reference proxy is used as an argument for optional<>. Best Fernando Cacciola SciSoft http://fcacciola.50webs.com/

"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
Specifically... wouldn't you find odd that the result of assignment depends on whether the lvalue was previously absent or not? Don't you agree that _most_ people would call _that_ counterintuitive?
That's what optional now does for non-reference types! If you're going to use assignment for the underlying type in optional<X>, then a special case for references that rebinds the reference seems wrong. OTOH, if you think that rebinding the reference is the right thing to do, then it is inconsistent to use assignment for non-reference types; these should be "rebound", too --- the old object destroyed, and a new one created. Special cases are awkward. Anthony -- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk

Anthony Williams wrote:
"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
Specifically... wouldn't you find odd that the result of assignment depends on whether the lvalue was previously absent or not? Don't you agree that _most_ people would call _that_ counterintuitive?
That's what optional now does for non-reference types!
Well, using your analogy below for non-reference types, yes, you're right. Well, finally something that can help me weight the models.
If you're going to use assignment for the underlying type in optional<X>, then a special case for references that rebinds the reference seems wrong.
Yes, special cases are awkard.. That's always the case and I always agreed with that. What is interesting of your post is that you have shown that this is indeed a special case since assignment of non-reference types does depend on the lvalue being absent or not. Is just that for non reference types, the difference is mot while for reference types is very important. Please, wait for my post on c.s.cpp so we can continue there. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Just to add to the noise on the subject of rebinding references ;?) I asked about the following example at the meeting, as I was concerned that despite several 'regular' users of optional being in the room, the only way anyone knew what it did was to compile the code and see the result. That seems too subtle a semantic to me. Once you learn it, it seems obvious so it is not a blocking issue for me. But it did raise a concern: int a = 13; int &b = a; int c = 42; optional< int & > d = b; d = c; Should this code compile? c is an int not an int &? Should it assign the value of c to a, so now a == 42? Or does it rebind the optional reference to c? In both compiling scenarios d == 42, so you need to remember to check a to conclude the experiment. For the curious, the current answer is option 3 - d rebinds a reference to c. I also think optional is fundamentally too useful to let it run into the ground over such issues ;?) -- AlisdairM

AlisdairM wrote:
int a = 13; int &b = a; int c = 42;
optional< int & > d = b; d = c;
<snip>
For the curious, the current answer is option 3 - d rebinds a reference to c.
Huh. IANAOU* but this seems surprising to me. I would expect this not to rebind the reference. Had I wanted that behavior, I would have used an int*, or else I would have done something like: optional< tr1::reference_wrapper<int> > d = b; or some such. Has interoperability with tr1::reference_wrapper<> been pursued as a means to give boost::optional<> reference rebinding semantics which are ... optional? ;-) * IANAOU == I am not an optional user -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
AlisdairM wrote:
int a = 13; int &b = a; int c = 42;
optional< int & > d = b; d = c;
<snip>
For the curious, the current answer is option 3 - d rebinds a reference to c.
Ha, very interesting experiment!! I agree the semantics are subtle, I aways did. Yet the as I've been trying to explain the alternative is even more subtle. I wonder what would be the result of the following thought experiment: Please, answer the questions _without_ looking at the answers, and if possible post your initial results; then compare with the answers. int a = 1; int b = 2 ; int c = 3 ; int &ra = a; int &rb = b; int &rc = c; optional<int&> o = ra; o = rb ; // [1] o = none ; o = rc ; [2] (a) What is the value of 'a' after [1]? (b) What is the value of 'a' after [2]? ANSWERS: If no-rebinding is used, the answers are: (a) 2 (b) 2 // Is not '3' because 'a' is "released" at 'o=none' If rebinding is used: (a) 1 // Is not '2' because 'a' is never changed (b) 1 // Is not '3' because 'a' is never changed
Huh. IANAOU* but this seems surprising to me. I would expect this not to rebind the reference. Had I wanted that behavior, I would have used an int*
Would you be able to use int* then you probably should. optional<int> is intended to allow you to express an absent 'int' without resorting to a pointer. (and please!, this doesn't mean at all that optional is a pointer... both optional<> and pointers are models of a more fundamental concept: OptionalPointee or Nullable) Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
(and please!, this doesn't mean at all that optional is a pointer... both optional<> and pointers are models of a more fundamental concept: OptionalPointee or Nullable)
I dislike the term OptionalPointee as it names the concept after a possible implementation <g> I DO like the term Nullable while the debate remains open ;?) Putting aside rebinding for now, one reason I would really like an optional type would be to divorce Nullability from pointer semantics. One reason pointers make bad Nullable types is that they reserve a value from the valid range to represent their null value. The whole reason to use optional< int > is to avoid that very problem. Consider: int * px = 0; optional< int * > ox1; optional< int * > ox2 = px; Is ox2 an optional value bound to a nulled value, or just a null value? How is it different to ox1, an unbound null value? int x = 1; int *px = &x; optional< int * > ox = px; *ox == 1? or *ox == px? There is no reason for these questions to confuse clear minds on a bright day, but removing the pointer interface could be clearer on the muggy midsummer days when you are trying to get the code out before a deadline... -- AlisdairM

From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
I wonder what would be the result of the following thought experiment: Please, answer the questions _without_ looking at the answers, and if possible post your initial results; then compare with the answers.
IANAOU either (yet!), but I'll give my answers. First, I'll describe what I think the right behavior is; this may be exactly how optional works now or it may not be. I haven't compared this description to optional's documentation. An optional<T&> should optionally contain a reference to T. Either optional<T&> has a T& or it doesn't. Since T& cannot be rebound, neither should optional<T&>'s T& be rebound by assignment from another T&. That said, assigning from none restores the optional<T&> to (the equivalent of) its default constructed state, so it can bind to a new T&. Thus, I don't consider the described behavior for optional<T&> as supporting rebinding because it is reset by assignment from none; it is not rebound by assignment from a T&.
int a = 1; int b = 2 ; int c = 3 ; int &ra = a; int &rb = b; int &rc = c;
optional<int&> o = ra;
You can't have a reference to a reference, so o contains a reference to a.
o = rb ; // [1]
Assigns b's value through o's reference to a. o still holds a reference to a.
o = none ;
No reference in o.
o = rc ; [2]
Now o contains a reference to c.
(a) What is the value of 'a' after [1]?
2
(b) What is the value of 'a' after [2]?
2 -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Hi, Rob Stewart wrote:
An optional<T&> should optionally contain a reference to T. Either optional<T&> has a T& or it doesn't. Since T& cannot be rebound, neither should optional<T&>'s T& be rebound by assignment from another T&. That said, assigning from none restores the optional<T&> to (the equivalent of) its default constructed state, so it can bind to a new T&.
I agree on that one. If the developer wanted a pointer, he'd have asked for it. Simon

How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not. Instead, to change the binding, use reset(), and to assign use *. optional<int> x; x.reset(3); // x now holds the value 3 x.reset(4); // x now holds a new int, value 4 *x=5; // change the value of the held int, to 5 x.reset(); // x now empty x=6; // error, no direct assignment x=optional<int>(6); // now holds a new int, value 6 struct NonAssignable { const int value; NonAssignable(int value_): value(value_) {} }; optional<NonAssignable> y; y.reset(NonAssignable(3)); // ok y.reset(NonAssignable(4)); // y now holds a new NonAssignable, value 4 *y=NonAssignable(5); // error, NonAssignable doesn't support assignment y.reset(); // y now empty y=NonAssignable(6); // error, no direct assignment y=optional<NonAssignable>(NonAssignable(6)); // now holds a new NonAssignable int a=1; int b=2; int c=3; optional<int&> z; z.reset(a); // ok --- reference to a z.reset(b); // ok --- reference to b *z=c; // assign 3 to b y.reset(); y=c; // error, no direct assignment y=optional<int&>(c); // now holds a ref to c Anthony -- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk

Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment." The assignment from T is really a kind of mutating operation.
Instead, to change the binding, use reset(), and to assign use *.
To make that valid for a null optional, I think operator* would have to return a proxy reference... which is not an altogether bad idea, IMO. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment."
The assignment from T is really a kind of mutating operation.
Indeed. I'm leaning fast into dropping assignment form T. That definitely solves the reference binding issues.
Instead, to change the binding, use reset(), and to assign use *.
To make that valid for a null optional, I think operator* would have to return a proxy reference... which is not an altogether bad idea, IMO.
That would actually bring back the problem as assignment to a null reference would bind and then there's the question about what to do with assignment to a non-null reference (rebind as I proposed or not-rebind as Joel proposed) But if we do as both Sam Partignton and Antony Williams suggest, drop assignment from T altoghether, the situation looks a lot more clear, at least to me. Antony's proposal goes even beyond Sam's idea: rather than dropping assignment from T, we spell it: reset(). That is definetly better then direct assignment from T, but I'm not quite sure that is as good a solution as keeping just copy assignment. Consider these 3 versions: int a = 1; int b = 2; int& ra = a ; int& rb = b ; optional<int&> o(ra); *o = rb ; // Clearly doesn't rebind but is UB if 'o' were null. // (1) Current case: o = rb ; // rebind or not?? // (2) Antonty's proposal: o.reset(rb); // still some room for doubts? // (3) Sam's proposal: o = make_optional(rb); // Clearly rebinds, doesn't it? // I just introduced make_optional() here to get rid of the template argument I think (3) spells the actual semantics (rebinding) even more clearly than (2). OTOH, both (2) and (3) are equivalent, so the difference is merely sintatical. Having said that, I prefer (3) which just looks better to my eyes, but (2) could work too. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment."
The assignment from T is really a kind of mutating operation.
Indeed. I'm leaning fast into dropping assignment form T. That definitely solves the reference binding issues.
Instead, to change the binding, use reset(), and to assign use *.
To make that valid for a null optional, I think operator* would have to return a proxy reference... which is not an altogether bad idea, IMO.
That would actually bring back the problem as assignment to a null reference would bind and then there's the question about what to do with assignment to a non-null reference (rebind as I proposed or not-rebind as Joel proposed) But if we do as both Sam Partignton and Antony Williams suggest, drop assignment from T altoghether, the situation looks a lot more clear, at least to me.
FWIW, I like the direction this is heading into. Dropping assignment from T altogether is a wise move! I wouldn't mind copy assignment and *explicit* construction. I wouldn't mind reset(T) too. IMO, that interface is orthogonal; and there's a clear precedent: shared_ptrs (which has both reset and copy assignment). Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Hi. I'm an optional<> user, and a big fan of it. I'm also unable to resist my temptation of expressing my opinion... :-) Fernando Cacciola wrote:
David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment."
The assignment from T is really a kind of mutating operation.
Indeed. I'm leaning fast into dropping assignment form T. That definitely solves the reference binding issues.
If that means that I'll have to write o = optional<T>(x); then I vote against. This is ugly...
Antony's proposal goes even beyond Sam's idea: rather than dropping assignment from T, we spell it: reset(). That is definetly better then direct assignment from T, but I'm not quite sure that is as good a solution as keeping just copy assignment.
Consider these 3 versions:
int a = 1; int b = 2; int& ra = a ; int& rb = b ;
optional<int&> o(ra);
*o = rb ; // Clearly doesn't rebind but is UB if 'o' were null.
// (1) Current case: o = rb ; // rebind or not??
// (2) Antonty's proposal: o.reset(rb); // still some room for doubts?
Plently of room for doubts. Actually, why calling it reset() makes it any different from an assignment operator? This is just the same, and the old "to rebind or not to rebind" question comes back, this time with respect to the reset() method.
// (3) Sam's proposal: o = make_optional(rb); // Clearly rebinds, doesn't it?
// I just introduced make_optional() here to get rid of the template argument
Oh, this is much better than the o = optional<int&>(rb) I just voted againts, but is it feasible? Can make_optional() know if it should make an optional<T> or optional<T&>? Perhaps a way can be found, but I'm not sure of it. In a more general context, I have to say that I've never used optional<T&>. Whenever I need to have an optional reference I use a pointer. So I tend to think of optional<T&> in terms of T*. This is why when the question first came up, I was in favour of rebinding - to do just as T* does. Then (after reading one of the posts in this thread) I thought that the same facts can lead me to the very opposite conclusion: if I can always use a plain T* for rebinding semantics, then optional<T&> can be left for the other use cases - i.e. no rebind. Anyway, as I said, I've never used optional<T&>, and I'm willing to let go of it completely, especially if it can save direct assignment from T... And even more especially if it will help my favourite library be accepted into the standard... ;-) Just one more thing: I feel the example shown by Peter Dimov was not properly addressed. In my words, a variant and an optional are very similar in a way that they both might be creating a previously absent object, as a result of an assignment operator. Both optional<T&> and variant<T&, ...> may or may not contain a T& object at a given moment, and thus should behave the same on assignment. May that behaviour be rebind or no-rebind, it should be applied to both. It's a pity that variant seems to be neglected recently (it might need repairs after a conclusion is reached)... Tuple, on the other hand, doesn't suffer from this issue, so I don't think it's a part of this debate. I hope I contributed something to the discussion, Yuval

Yuval Ronen wrote:
// (3) Sam's proposal: o = make_optional(rb); // Clearly rebinds, doesn't it?
// I just introduced make_optional() here to get rid of the template argument
Oh, this is much better than the
o = optional<int&>(rb)
I just voted againts, but is it feasible? Can make_optional() know if it should make an optional<T> or optional<T&>? Perhaps a way can be found, but I'm not sure of it.
It would be: o = optional_tie(rb); for references. Following tuple's "tie". Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

On 10/18/05, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment."
The assignment from T is really a kind of mutating operation.
Indeed. I'm leaning fast into dropping assignment form T. That definitely solves the reference binding issues.
[snip] Please review this dicsussion thread from 2003 < http://aspn.activestate.com/ASPN/Mail/Message/boost/1788454> before discarding assignment from T. - Mat

Mat Marcus wrote:
On 10/18/05, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment."
The assignment from T is really a kind of mutating operation.
Indeed. I'm leaning fast into dropping assignment form T. That definitely solves the reference binding issues.
[snip]
Please review this dicsussion thread from 2003 < http://aspn.activestate.com/ASPN/Mail/Message/boost/1788454> before discarding assignment from T.
I just read it but got sort of lost past the "uniformity with tie" issue. Can you recap your own issues with dropping direct assignment? TIA -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On Tue, 2005-10-18 at 14:52 -0300, Fernando Cacciola wrote:
// (1) Current case: o = rb ; // rebind or not??
// (2) Antonty's proposal: o.reset(rb); // still some room for doubts?
// (3) Sam's proposal: o = make_optional(rb); // Clearly rebinds, doesn't it?
// I just introduced make_optional() here to get rid of the template argument
I am kind of diving in here having not read much of the option< T & > stuff in this thread, but how about.. o = make_optional( &rb ); To balance the indirection of *o and o-> Also, could be compatible with pointers int * p = make_optional( &rb ); o = make_optional( p ); p = make_optional( o ); See my earlier post for an example (I used "opt" instead of "make_optional"). Hamish PS. I know, I was the one arguing against pointer interfaces a few hours ago and now I want more :-) (but not safe_bool, "!o" or "o != 0")

Hamish Mackenzie wrote:
I am kind of diving in here having not read much of the option< T & > stuff in this thread, but how about..
o = make_optional( &rb );
No, that wouldn't work. A reference can't be bound to an object indirectly through a pointer to it, you need the object itself. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
// (2) Anthony's proposal: o.reset(rb); // still some room for doubts?
How about o.replace_with(rb); does that suggest rebinding? I was imagining that reset (or replace_with) would always rebind/replace the contained element, rather than assign to it. Then it would also work with my non-assignable types.
// (3) Sam's proposal: o = make_optional(rb); // Clearly rebinds, doesn't it?
I could run with this. As for Mat's concerns about using optionals in place of normal values: * if the conversion constructor is not explicit, then that allows constructing an optional<T> from a T * we could provide a means of capturing a value into an optional: std::pair<Foo, Bar> do_stuff(); boost::optional<Foo> foo; boost::optional<Bar> bar; tie(rebinder(foo),rebinder(bar))=do_stuff(); Anthony -- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk

Anthony Williams wrote:
"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
// (2) Anthony's proposal: o.reset(rb); // still some room for doubts?
How about
o.replace_with(rb);
does that suggest rebinding?
Why not just o.rebind(rb)? -Jason

Jason Hise wrote:
Anthony Williams wrote:
"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
// (2) Anthony's proposal: o.reset(rb); // still some room for doubts?
How about
o.replace_with(rb);
does that suggest rebinding?
Why not just o.rebind(rb)?
Perfect! At least if direct assignment is handled via a member function. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

From: Anthony Williams <anthony_w.geo@yahoo.com>
"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
// (2) Anthony's proposal: o.reset(rb); // still some room for doubts?
How about
o.replace_with(rb);
I don't think that's any better and it is more verbose.
does that suggest rebinding? I was imagining that reset (or replace_with)
I can just as easily infer assignment as rebinding. Jason Hise's suggestion of rebind() would be quite explicit and could be optimized to just do assignment for builtin types.
would always rebind/replace the contained element, rather than assign to it. Then it would also work with my non-assignable types.
Yes, an interface for non-assignable types that doesn't requiring parameterizing optional would be good. IOW, o.rebind(rb) rather than o = optional<T&>(rb).
* we could provide a means of capturing a value into an optional:
std::pair<Foo, Bar> do_stuff(); boost::optional<Foo> foo; boost::optional<Bar> bar;
tie(rebinder(foo),rebinder(bar))=do_stuff();
s/rebinder/rebind/ That looks nice. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
Yes, an interface for non-assignable types that doesn't requiring parameterizing optional would be good. IOW, o.rebind(rb) rather than o = optional<T&>(rb).
Right. make_optional(v) doesn't work because it can't tell whether we want a T or a T& optional_tie() would work but it requires the user to know wheter T or T& is needed. direct assignment is troublesome. So the only choices I see are: o.rebind(rb) or o = optional<T&>(rb). And I think I like the rebind() better. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
Rob Stewart wrote:
Yes, an interface for non-assignable types that doesn't requiring parameterizing optional would be good. IOW, o.rebind(rb) rather than o = optional<T&>(rb).
Right.
make_optional(v) doesn't work because it can't tell whether we want a T or a T&
optional_tie() would work but it requires the user to know wheter T or T& is needed.
direct assignment is troublesome.
So the only choices I see are:
o.rebind(rb)
or
o = optional<T&>(rb).
And I think I like the rebind() better.
I like the latter. The name "rebind" doesn't make much sense for optional<T> where T is not a reference. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
So the only choices I see are:
o.rebind(rb)
or
o = optional<T&>(rb).
And I think I like the rebind() better.
One more reason to keep the latter: don't you want to be able to put optional's in std::containers? I think it's important that they be proper values; disabling assignment altogether would be bad, and I don't think I want optional<T&>'s assignment operator to deep-copy the T. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Fernando Cacciola" <fernando_cacciola@hotmail.com> writes:
So the only choices I see are:
o.rebind(rb)
or
o = optional<T&>(rb).
And I think I like the rebind() better.
One more reason to keep the latter: don't you want to be able to put optional's in std::containers? I think it's important that they be proper values; disabling assignment altogether would be bad, and I don't think I want optional<T&>'s assignment operator to deep-copy the T.
Oh, I wasn't thinking at all on disabling copy assignment. That will definitely stay. But since you need to spell the contained type to use copy assignment I was considering _additional_ methods that can make the assignment syntactically easier. A member fuction like rebind() is one alternative, but yes, there is the problem that it makes little sense with non-rerefence types. I suggested to add: make_optional(v); as a shortcut for: optional<some_type>(v). People argued, with reason, that you still need to discriminate yourself references from non-references (so you would need to use a different shortcut, like, make_optional_ref(r)) But actually I don't think having to discriminate that explicitely is much of a probem. So my current proposal would be: Remove direct-assignment. Let copy-assigment be the only way to define the wrapped value Add make_optional() and make_optional_ref() as shorcuts to help with copy-assignment Keep none-assignment as the only wat to clear the wrapped value. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

I suggested to add:
make_optional(v);
as a shortcut for:
optional<some_type>(v).
People argued, with reason, that you still need to discriminate yourself references from non-references (so you would need to use a different shortcut, like, make_optional_ref(r))
How about : o = make_optional(boost::ref(t)); But actually I'd rather say it explicitly all the time with optional<T>(t)
So my current proposal would be:
Remove direct-assignment. Let copy-assigment be the only way to define the wrapped value Add make_optional() and make_optional_ref() as shorcuts to help with copy-assignment Keep none-assignment as the only wat to clear the wrapped value.
That gets my vote. I'm not especially bothered whether make_optional and make_optional_ref go in or not, the user can decided whether they want to use it or not. Sam

Fernando Cacciola wrote:
So my current proposal would be:
Remove direct-assignment. Let copy-assigment be the only way to define the wrapped value Add make_optional() and make_optional_ref() as shorcuts to help with copy-assignment Keep none-assignment as the only wat to clear the wrapped value.
Does this mean that construction from T is also suggested to be removed? I assume not... Anyway, If I'm required to write optional<T> o = x; ... o = optional<T>(y); or optional<T> o = x; ... o = make_optional(y); then it should be considered that this generates an additional temporary instance of y (of type T). Direct assignment from T doesn't suffer from this. Working around this makes me write optional<T>(y).swap(o); or make_optional(y).swap(o); which is completely different...

Yuval Ronen wrote:
optional<T>(y).swap(o);
or
make_optional(y).swap(o);
which is completely different...
which can be a terrible idea (it just occurred to me), depends on how optional's swap is implemented, and if/how T can be efficiently swaped...

Yuval Ronen wrote:
Fernando Cacciola wrote:
So my current proposal would be:
Remove direct-assignment. Let copy-assigment be the only way to define the wrapped value Add make_optional() and make_optional_ref() as shorcuts to help with copy-assignment Keep none-assignment as the only wat to clear the wrapped value.
Does this mean that construction from T is also suggested to be removed? I assume not...
You assume correct.
Anyway, If I'm required to write
optional<T> o = x; ... o = optional<T>(y);
or
optional<T> o = x; ... o = make_optional(y);
then it should be considered that this generates an additional temporary instance of y (of type T). Direct assignment from T doesn't suffer from this.
Good point. Still, I'm not sure this is significant enough to go back to direct assigment though. Specially given that this is precisely the situation rvalue references are for (and I think we can safely bet they will be part of C++ even before optional<>).
Working around this makes me write
optional<T>(y).swap(o);
or
make_optional(y).swap(o);
which is completely different...
Ya, that's reasonable alternative. I wouldn't worry too much about it though, chances are C++ will soon overcome clearly unnecesary temporaties like that without such code gymnastics. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola writes:
So my current proposal would be:
Remove direct-assignment.
Ouch. Personally, I think that in the race to satisfy the conflicting forces in the marginal number of use cases we are throwing the baby along with the water. Here at Meta we use optional very extensively, we never had a use case for holding a reference, and we use direct assignment very often. In fact, I consider it to be an essential element in the consistency of the current interface, which we found to be very intuitive and easy to explain, adopt and use across our teams. IMO there have to be strong reasons to override this kind of experience reports and radically rework the class interface, and for me none of the argumentation that led to the current state of discussion seemed to provide these reasons. -- Aleksey Gurtovoy MetaCommunications Engineering

From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
Antony's proposal goes even beyond Sam's idea: rather than dropping assignment from T, we spell it: reset(). That is definetly better then direct assignment from T, but I'm not quite sure that is as good a solution as keeping just copy assignment.
Consider these 3 versions:
int a = 1; int b = 2; int& ra = a ; int& rb = b ;
optional<int&> o(ra);
*o = rb ; // Clearly doesn't rebind but is UB if 'o' were null.
// (1) Current case: o = rb ; // rebind or not??
// (2) Antonty's proposal: o.reset(rb); // still some room for doubts?
That is better because one needs to know its behavior; it's a bit harder to assume you know what reset() does than what assignment does. Your concern that using reset() makes optional look that much more like a smart pointer, belying the difference in deep versus shallow copying isn't as significant as you make it out to be. Not all smart pointers do deep copies and yet reset() is a sensible name. Thus, I think reset() is a reasonable name, precisely because optional is so much like a smart pointer. OTOH, I suggest that reset() take no arguments and only be a (the?) way to "unbind" the optional. IOW, rebinding should be spelled differently.
// (3) Sam's proposal: o = make_optional(rb); // Clearly rebinds, doesn't it?
// I just introduced make_optional() here to get rid of the template argument
As mentioned elsewhere, this won't understand how to deal with references versus non-references correctly. You need the user to indicate when a reference should really be a reference in the optional.
I think (3) spells the actual semantics (rebinding) even more clearly than (2). OTOH, both (2) and (3) are equivalent, so the difference is merely sintatical. Having said that, I prefer (3) which just looks better to my eyes, but (2) could work too.
I think copy construction is quite obvious and removes the (non-)reference confusion of make_optional(). -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
Antony's proposal goes even beyond Sam's idea: rather than dropping assignment from T, we spell it: reset(). That is definetly better then direct assignment from T, but I'm not quite sure that is as good a solution as keeping just copy assignment.
Consider these 3 versions:
int a = 1; int b = 2; int& ra = a ; int& rb = b ;
optional<int&> o(ra);
*o = rb ; // Clearly doesn't rebind but is UB if 'o' were null.
// (1) Current case: o = rb ; // rebind or not??
// (2) Antonty's proposal: o.reset(rb); // still some room for doubts?
That is better because one needs to know its behavior; it's a bit harder to assume you know what reset() does than what assignment does.
Your concern that using reset() makes optional look that much more like a smart pointer, belying the difference in deep versus shallow copying isn't as significant as you make it out to be. Not all smart pointers do deep copies and yet reset() is a sensible name. Thus, I think reset() is a reasonable name, precisely because optional is so much like a smart pointer.
OTOH, I suggest that reset() take no arguments and only be a (the?) way to "unbind" the optional. IOW, rebinding should be spelled differently.
So you'd prefer: o.reset() to o = none ? Well, I guess that's depend on what with do with assigment. If there's only copy assignment, 'o = none' looks consistent. If there is rebind(), reset() looks consistent.
As mentioned elsewhere, this won't understand how to deal with references versus non-references correctly. You need the user to indicate when a reference should really be a reference in the optional.
Right, so we need something else.
I think (3) spells the actual semantics (rebinding) even more clearly than (2). OTOH, both (2) and (3) are equivalent, so the difference is merely sintatical. Having said that, I prefer (3) which just looks better to my eyes, but (2) could work too.
I think copy construction is quite obvious and removes the (non-)reference confusion of make_optional().
The only problem I see with copy assignment is that it requires you to spell out the wrapped type; that can be a nuisanse. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
So you'd prefer:
o.reset()
to
o = none
?
Well, I guess that's depend on what with do with assigment.
If there's only copy assignment, 'o = none' looks consistent. If there is rebind(), reset() looks consistent.
I humbly disagree. I think that if there's no direct assignment from T, then there should also be no direct assignment from none (these two are symmetric, as they are the two possible options for the optional's content), and the only way to do it is by using reset()/clear(), or copy assignment from an empty optional. If there is direct T assignment, on the other hand, then none assignment should follow.

Speaking as a rank amateur (relative to everyone else posting about this), the last few postings seem to me to be heading in a more promising direction than the stark "rebind/no-rebind" debate. David Abrahams wrote:
Anthony Williams <anthony_w.geo@yahoo.com> writes:
How's this for a radical thought --- optional<T> should not be assignable from T. That way, it doesn't matter whether T is a reference, or not.
There's at least some precedent for types that are "immutable except for copy assignment."
The assignment from T is really a kind of mutating operation.
Instead, to change the binding, use reset(), and to assign use *.
To make that valid for a null optional, I think operator* would have to return a proxy reference... which is not an altogether bad idea, IMO.

Rob Stewart wrote:
From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
I wonder what would be the result of the following thought experiment: Please, answer the questions _without_ looking at the answers, and if possible post your initial results; then compare with the answers.
IANAOU either (yet!), but I'll give my answers.
First, I'll describe what I think the right behavior is; this may be exactly how optional works now or it may not be. I haven't compared this description to optional's documentation.
OK. You just described Joel's proposed behaviour, and, from your test results, it's clear that at least you wouldn't be confused about the fact that in one case it binds while in the other it doesn't. Now I wonder how would that be in real code... I mean, in my example you could infer from the context that 'o' was null in one of the cases... but what if you can't tell that? you wouldn't be able from context alone to know the expected effect of assignment. That's real problem don't you agree? Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Rob Stewart wrote:
From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
I wonder what would be the result of the following thought experiment: Please, answer the questions _without_ looking at the answers, and if possible post your initial results; then compare with the answers.
IANAOU either (yet!), but I'll give my answers.
First, I'll describe what I think the right behavior is; this may be exactly how optional works now or it may not be. I haven't compared this description to optional's documentation.
OK. You just described Joel's proposed behaviour, and, from your test results, it's clear that at least you wouldn't be confused about the fact that in one case it binds while in the other it doesn't. Now I wonder how would that be in real code... I mean, in my example you could infer from the context that 'o' was null in one of the cases... but what if you can't tell that? you wouldn't be able from context alone to know the expected effect of assignment. That's real problem don't you agree?
For the record, that is not exactly my proposed behaviour. I am objecting to *any* form of bind/rebind *from assignment*. Maybe that was not clear (as I noticed from Peter Dimov's reply) but what I am advocating is bind only at construction time (see my reply to Peter Dimov). Anyway, I like the new direction this is heading into (i.e. no assigment from T and the reset(), reset(nil), reset(T) syntax). Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Joel de Guzman wrote:
Fernando Cacciola wrote:
Rob Stewart wrote:
From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
I wonder what would be the result of the following thought experiment: Please, answer the questions _without_ looking at the answers, and if possible post your initial results; then compare with the answers.
IANAOU either (yet!), but I'll give my answers.
First, I'll describe what I think the right behavior is; this may be exactly how optional works now or it may not be. I haven't compared this description to optional's documentation.
OK. You just described Joel's proposed behaviour, and, from your test results, it's clear that at least you wouldn't be confused about the fact that in one case it binds while in the other it doesn't. Now I wonder how would that be in real code... I mean, in my example you could infer from the context that 'o' was null in one of the cases... but what if you can't tell that? you wouldn't be able from context alone to know the expected effect of assignment. That's real problem don't you agree?
For the record, that is not exactly my proposed behaviour. I am objecting to *any* form of bind/rebind *from assignment*. Maybe that was not clear (as I noticed from Peter Dimov's reply) but what I am advocating is bind only at construction time (see my reply to Peter Dimov).
Ha yes, you are right.. You just once mentioned that you could live with rebinding from copy assignment at most.
Anyway, I like the new direction this is heading into
Me too! Finally getting somewhere.
(i.e. no assigment from T and the reset(), reset(nil), reset(T) syntax).
Well, I'm not so sure about reset(). My very first boost submision had reset() and no assignment from T, exactly as we are considering now. But the big problem, and it was big, was that it just made people be even more confused about optional<> being yet another smart pointer (precisey becasue auto_ptr and shared_ptr uses it). AFAICT, the choice between: o = make_optional(val); o = nullptr ; and o.reset(val); o.reset(); is just cosmetical.. and at that, I prefer the first version because it pushes optional<> away from a smart_ptr. IOW, that it uses * and -> just like any other nullable type makes sense because the semantics of these operators are the same for all nullable types; but the semantics of reset() in the case of optional<> are different from those of a smart ptr (deep vs shallow). Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Joel de Guzman wrote:
(i.e. no assigment from T and the reset(), reset(nil), reset(T) syntax).
Well, I'm not so sure about reset(). My very first boost submision had reset() and no assignment from T, exactly as we are considering now. But the big problem, and it was big, was that it just made people be even more confused about optional<> being yet another smart pointer (precisey becasue auto_ptr and shared_ptr uses it).
AFAICT, the choice between:
o = make_optional(val); o = nullptr ;
and
o.reset(val); o.reset();
is just cosmetical.. and at that, I prefer the first version because it pushes optional<> away from a smart_ptr.
IOW, that it uses * and -> just like any other nullable type makes sense because the semantics of these operators are the same for all nullable types; but the semantics of reset() in the case of optional<> are different from those of a smart ptr (deep vs shallow).
Then perhaps you should consider the other examples of similar semantics in the STL. Specifically the clear() and assign() interface of containers. I.e.: o.assign(val); o.clear(); That looks obviously not pointer like to me. And clear enough as to the meaning. But of course it brings to mind the idea that it's just a single value container, and hence possibly should have some more of those interfaces. Just a thought :-) -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - Grafik/jabber.org

From: Rene Rivera <grafik.list@redshift-software.com>
o.assign(val); o.clear();
That looks obviously not pointer like to me. And clear enough as to the meaning. But of course it brings to mind the idea that it's just a single value container, and hence possibly should have some more of those interfaces.
I suspect that adding container-like functions to the pointer interface will do more harm than good. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Rene Rivera <grafik.list@redshift-software.com>
o.assign(val); o.clear();
That looks obviously not pointer like to me. And clear enough as to the meaning. But of course it brings to mind the idea that it's just a single value container, and hence possibly should have some more of those interfaces.
I suspect that adding container-like functions to the pointer interface will do more harm than good.
The pointer interface is exclusively for value access. I don't see a real problem using member functions for the other operations, like assignment and clearing. Altough I do prefer to use unique names if possible. rebind() is perfect. clear() rings better than reset() to me. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola wrote:
Joel de Guzman wrote:
Anyway, I like the new direction this is heading into
Me too! Finally getting somewhere.
Great!
(i.e. no assigment from T and the reset(), reset(nil), reset(T) syntax).
Well, I'm not so sure about reset().
Understood. Copy assignment would suffice. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

From: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
Rob Stewart wrote:
First, I'll describe what I think the right behavior is; this may be exactly how optional works now or it may not be. I haven't compared this description to optional's documentation.
OK. You just described Joel's proposed behaviour, and, from your test results, it's clear that at least you wouldn't be confused about the fact that in one case it binds while in the other it doesn't. Now I wonder how would that be in real code... I mean, in my example you could infer from the context that 'o' was null in one of the cases... but what if you can't tell that? you wouldn't be able from context alone to know the expected effect of assignment. That's real problem don't you agree?
I agree that's a real problem and even more so in generic code that might try to work with any OptionalPointee. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Howard Hinnant writes:
On Oct 10, 2005, at 10:36 AM, Fernando Cacciola wrote:
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported?
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
IIRC, the developers list's archive keeps an extensive discussion of the use cases and possible variants of this functionality.
General question: what shall I do from now on? Follow the discussions on comp.std.c++?
This is a good question, and I can only give an opinion (as opposed to an authoritative answer).
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
and which dropped reference support. Then perhaps submit a follow on paper reflecting that experience. Said paper may either modify your current proposal, or more fully support it.
-- Aleksey Gurtovoy MetaCommunications Engineering

Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation.
That's how I see it too. IMO, the pointer interface is just too practical to be dropped in the name of "<add your adjetive here> programmer protection"
That said, moral positions count when they are connected to votes in the committee,
Very good point.
so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor.
OK.. here we go. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uzmpgktlc.fsf@boost-consulting.com...
Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor.
Agreed. And a good way to do that is to produce an updated version of the proposal with several use cases showing actual code using both interfaces, and pointing out exactly how the pointer interface is superior. --Beman BTW, and updated proposal needs to have a new document number.

Beman Dawes wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uzmpgktlc.fsf@boost-consulting.com...
Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor.
Agreed. And a good way to do that is to produce an updated version of the proposal with several use cases showing actual code using both interfaces, and pointing out exactly how the pointer interface is superior. OK. I'll do that.
Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On Thu, 2005-10-13 at 13:51 -0300, Fernando Cacciola wrote:
Agreed. And a good way to do that is to produce an updated version of the proposal with several use cases showing actual code using both interfaces, and pointing out exactly how the pointer interface is superior. OK. I'll do that.
Don't forget to include this http://boost.org/libs/optional/doc/optional.html#bool as a counter example. Currently we are using a wrapper around boost::optional that hides the pointer interface and provides instead empty() and value() (though has_value() and value() may be better to avoid confusion for things like optional<Some_STD_Container>). We use optional<bool> all over the place in classes read/written from databases and xml. Refactoring a bool to an optional<bool> would be a nightmare with the pointer interface. It is made worse by the fact that we generate some C++ code from the DB schema so someone changing from a "bit not null" to a "bit null" (aka "boolean null") in a table definition would quietly break our code at runtime (instead of causing a compiler error in the appropriate place). Hamish

On Tue, 11 Oct 2005 10:37:35 -0400, David Abrahams wrote
Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor.
The orginal objection came from Mat Marcus and was simple -- he had to support more junior programmers who somehow become confused by the pointer interface. So this wasn't a theoretical or moral argument, but rather an in the trenches user report. As I recall the discussion, he was still a supporter of the proposal overall. You might want to try and get with Mat offline... Jeff Jeff

"Jeff Garland" <jeff@crystalclearsoftware.com> writes:
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor.
The orginal objection came from Mat Marcus and was simple -- he had to support more junior programmers who somehow become confused by the pointer interface.
Understandable. However, many of our most elegant interfaces are prone to confuse the uninitiated. I just had to clarify to someone that the parameter library interface is threadsafe and doesn't mutate any global state.
So this wasn't a theoretical or moral argument, but rather an in the trenches user report. As I recall the discussion, he was still a supporter of the proposal overall. You might want to try and get with Mat offline...
I did speak to Mat about it in Quebec. I'll let him continue to speak for himself, though. :) -- Dave Abrahams Boost Consulting www.boost-consulting.com

On 10/11/05, David Abrahams <dave@boost-consulting.com> wrote: Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor. -- Dave Abrahams Dave's "experience" of the objections to the pointer-like syntax as being "moral positions not backed up by any sound technical argumentation" would have been different had he actually been present at the discussion. Here are a few of the objections to the pointer interface that were raised in the discussion: 1) At a large company, I promoted and supported the use of optional. It was my experience that the pointer-like syntax confused a number of programmers. They were not "junior" programmers. The confusion centered around whether optional<Foo> had value semantics or pointer semantics, especially under copying. (Ironically, when the straw vote was taken as to whether to continue pursuing optional for the standard, I voted a "strong yes", while another committee member indicated that he was presently leaning towards a no vote since "we have enough shared_ptr-like components in the library already". Of course, as the proposal advances further, I expect him to study it more carefully.) 2) Regarding the Concept behind the pointer-like interface--an argument like the following argument would not work for me: "Pointers can be null or dereference-able, Optionals can be null or dereferenceable, therefor Optionals are models of Pointers". At best, this would argue that Optional and Pointer have one dimension of commonality, i.e. perhaps they would both model a more primitive concept (Nullable?). But there is also a dimension of variability, in particular, Optionals have deep-copy semantics, while pointer-like syntax suggests shallow copy semantics to many users. I did not claim that there were no arguments that the pointer-like interface was technically sound. Rather I suggested that we ask the author to consider the objections and if he was still convinced of the correctness of the interface, to provide us with rationale beyond that found in N1878. N1878's argument that "from syntax alone, [the pointer-like syntax makes it] loudly clear that the value being accessed might be absent" is offset in my mind by the fact that I have seen the syntax incorrectly suggest pointer-like copy semantics to users. My field experience supporting optional contradicts N1878's claim "the confusion is harmless". 3) Other committee members didn't want to see both a "get" and a pointer-like interface. To be fair to Dave, perhaps his impression came from a later discussion that we had in the lobby. In that discussion, after a while, we moved from the objections to optional's pointer-like interface to a discussion, "by analogy", of whether it was reasonable for string concatenation to be spelled "+". I argued that it was an embarrassment, since in mathematics "+" suggests that a+b == b+a, and I said that if we had to have an operator syntax for concatenation I might prefer "*". Dave argued that most programmers don't recall the meaning of the word Abelian, and that "*" would make for many unhappy programmers. From there we started talking about other languages. Of the lobby discussion, it could be said that there was "moralizing" in the air. (Please, let's not get into a discussion of std::string here). - Mat

Mat Marcus <mat-lists@emarcus.org> writes:
Having not used optional extensively, I don't have a strong opinion on which interface might be better, but it's been my experience that objections to the pointer interface seem to be moral positions not backed up by any sound technical argumentation. That said, moral positions count when they are connected to votes in the committee, so if there's a general consensus against the pointer interface there, the onus is on those in favor of it to produce sound argumentation in favor.
-- Dave Abrahams
Dave's "experience" of the objections to the pointer-like syntax as being "moral positions not backed up by any sound technical argumentation" would have been different had he actually been present at the discussion.
Hey, I didn't say my experience was extensive :)
Here are a few of the objections to the pointer interface that were raised in the discussion:
1) At a large company, I promoted and supported the use of optional. It was my experience that the pointer-like syntax confused a number of programmers. They were not "junior" programmers. The confusion centered around whether optional<Foo> had value semantics or pointer semantics, especially under copying.
That is a real issue.
(Ironically, when the straw vote was taken as to whether to continue pursuing optional for the standard, I voted a "strong yes", while another committee member indicated that he was presently leaning towards a no vote since "we have enough shared_ptr-like components in the library already".
Wow, that's a little scary. Was that someone who's generally on the ball, or one of those very few who sometimes vociferously object to what's being proposed on the grounds that it doesn't do the very thing it actually does?
Of course, as the proposal advances further, I expect him to study it more carefully.)
That would be nice, wouldn't it?
To be fair to Dave, perhaps his impression came from a later discussion that we had in the lobby.
Well, that was part of it, and it was the only experience I had of your point of view on the matter. However, I've heard similar objections in this list, so I wasn't basing my remarks only on our conversation. I think it's a simple question of whether the implication of reference semantics is strong and problematic enough to warrant changing. I don't know how we measure that. I wonder if your people would've been less confused had the optional<> docs contained a large Warning: This is not a pointer. It uses pointer syntax, but when an nonempty optional<T> is copied, it copies the T as well. An optional<T> object always occupies at least sizeof(T) bytes of storage. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Wow, that's a little scary. Was that someone who's generally on the ball, or one of those very few who sometimes vociferously object to what's being proposed on the grounds that it doesn't do the very thing it actually does?
I don't like the direction this is going in. Let's just say that my presentation of optional was not detailed enough for people not familiar with the concept. Mea culpa. Thomas -- Thomas Witt witt@acm.org

Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
Wow, that's a little scary. Was that someone who's generally on the ball, or one of those very few who sometimes vociferously object to what's being proposed on the grounds that it doesn't do the very thing it actually does?
I don't like the direction this is going in. Let's just say that my presentation of optional was not detailed enough for people not familiar with the concept. Mea culpa.
This isn't about whose fault it was. I'm not gonna play the blame game ;-) In evaluating the alleged dangers of the pointer syntax, it's important to understand why someone may have thought optional was supposed to be like shared_ptr. Was it just that the person doesn't pay attention? As it turns out, that person emailed me privately and the problem was nothing like that at all. Apparently he was concerned about something else and just expressed himself badly, so I'm back to not being so very scared about optional having dereference syntax. I'm just wondering, for those listening, whether the deep-copying smart pointers often used for the pimpl idiom raise the same concerns. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
This isn't about whose fault it was. I'm not gonna play the blame game ;-)
Come on. You're spoiling all the fun ;-)
I'm just wondering, for those listening, whether the deep-copying smart pointers often used for the pimpl idiom raise the same concerns.
Good point. I am still unconvinced that the syntax for value access is a good indicator for a type's copy semantics. auto_ptr anybody? Thomas -- Thomas Witt witt@acm.org

Thomas Witt wrote:
David Abrahams wrote:
Wow, that's a little scary. Was that someone who's generally on the ball, or one of those very few who sometimes vociferously object to what's being proposed on the grounds that it doesn't do the very thing it actually does?
I don't like the direction this is going in. Let's just say that my presentation of optional was not detailed enough for people not familiar with the concept. Mea culpa.
Don't blame it on your self ;) You've done an excelent job as shown by the results (the proposal moving forward). Thank you! This is a long standing issue, the interface I proposed was from the beggining loved and hated... and it will keep being like that even if I manage to convince most members that is a good idea. Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Aleksey Gurtovoy wrote:
Howard Hinnant writes:
On Oct 10, 2005, at 10:36 AM, Fernando Cacciola wrote:
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported?
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
IIRC, the developers list's archive keeps an extensive discussion of the use cases and possible variants of this functionality.
Indeed. I will collect them, put them in a single doc, and add it to my web site for reference.
General question: what shall I do from now on? Follow the discussions on comp.std.c++?
This is a good question, and I can only give an opinion (as opposed to an authoritative answer).
You might explore a interface here on boost which did not have the pointer interface,
Over my dead body ;). That's the interface we use here at Meta, and to say that our 'boost::optional' usage is extensive would be an understatement. We don't care for 'get', though.
Neither do I really.. that was just an oversight. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Howard Hinnant wrote:
On Oct 10, 2005, at 10:36 AM, Fernando Cacciola wrote:
Hi people, Not only I wasn't there at the mettings but from Thuesday night I was undergoing an emergency gall bladder surgery so I coulnd't even respond the email. But I'm back home now... still recovering but I can sit in front of the notebook :)
Wow, I surely hope you recover fast.
Thank you!
Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface:
Pointer interface.
It figues. FWIW, I'll stand strong on this part of the interface... though I'm not sure how much my position can affect the final TR2 form.
Two ways of doing the same thing.
Hmm, really? Did they gave examples?
I believe this refers to the pointer interface plus get().
Oh.. what is get() doing there? ;)
Depends on nullptr - is there a backup plan.
I could have proposed 'none' along Optional, in its own context, but that would duplicate much of nullptr... I didn't see the need for such duplication.
Dubious of use of references.
Does this mean they don't see that as useful or that is not well supported?
I believe there was specific concern about reference rebinding under optional<T&>. There were also several comments that went like: I use optional all the time (gives use case), but I've never needed to use it with reference types.
Hmm, well, as I'll explain in the response to Joel the "normal" semantics for references are even more troubled; but I see how this can be an endless debate.
General question: what shall I do from now on? Follow the discussions on comp.std.c++?
This is a good question, and I can only give an opinion (as opposed to an authoritative answer).
You might explore a interface here on boost which did not have the pointer interface, and which dropped reference support. Then perhaps submit a follow on paper reflecting that experience. Said paper may either modify your current proposal, or more fully support it.
Well, I can certainly code up a, say, nullable<> type to explore other interface choices; but I'm unsure how to get proper feedback. Boost.Optional has been here for a while now, yet apart from the detailed feedback of just a couple of users, all I know is that people use it; but that's it... I don't get to see how much do they like/diskike this and that of the interface/semantics. So, how could I eventually compare the pros/cons of both interfaces? ..maybe I should post a "call for public report on optional" or so... Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

Fernando Cacciola writes:
Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface:
Pointer interface.
It figues. FWIW, I'll stand strong on this part of the interface... though I'm not sure how much my position can affect the final TR2 form.
If you need more support/real-world experience reports on this, just shout. -- Aleksey Gurtovoy MetaCommunications Engineering

Aleksey Gurtovoy wrote:
Fernando Cacciola writes:
Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface:
Pointer interface.
It figues. FWIW, I'll stand strong on this part of the interface... though I'm not sure how much my position can affect the final TR2 form.
If you need more support/real-world experience reports on this, just shout.
OK I'm shouting loud :) ...but not here; soon I will raise the issue on c.s.cpp were it belongs now. -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/

On Sun, 9 Oct 2005 21:32:30 -0400, "Beman Dawes" <bdawes@acm.org> wrote: [...]
String-algo : Interested, but concern over interface and choice of functions, generic vs basic_string.5.3 separate proposal
Any details on this? I love this library, and I would love to see it standardized in some form. Overall I've found the interface and function choices to be excellent (and I'd love to see even more), and I love that it's generic and not limited to basic_string. I use it on vectors and other containers for different kinds of network protocol parsing. -- Be seeing you.

"Thore Karlsen" <sid@6581.com> wrote in message news:mv2lk1ldeo87dekbjkku3h39f7egqmh347@4ax.com...
On Sun, 9 Oct 2005 21:32:30 -0400, "Beman Dawes" <bdawes@acm.org> wrote:
[...]
String-algo : Interested, but concern over interface and choice of functions, generic vs basic_string.5.3 separate proposal
Any details on this? I love this library, and I would love to see it standardized in some form. Overall I've found the interface and function choices to be excellent (and I'd love to see even more), and I love that it's generic and not limited to basic_string. I use it on vectors and other containers for different kinds of network protocol parsing.
Thorsten Ottosen acted as champion for the paper, but I'll try to recall the discussion. There concern was that at least some of the algorithms were only useful in the context of strings, and so it would be an over-generalization to supply them as free algorithms. One way to counter that argument would be to identify the functions you have found useful on other containers, and to provide some use cases to buttress the argument. --Beman

On Mon, 10 Oct 2005 15:14:19 -0400, "Beman Dawes" <bdawes@acm.org> wrote:
String-algo : Interested, but concern over interface and choice of functions, generic vs basic_string.5.3 separate proposal
Any details on this? I love this library, and I would love to see it standardized in some form. Overall I've found the interface and function choices to be excellent (and I'd love to see even more), and I love that it's generic and not limited to basic_string. I use it on vectors and other containers for different kinds of network protocol parsing.
Thorsten Ottosen acted as champion for the paper, but I'll try to recall the discussion.
There concern was that at least some of the algorithms were only useful in the context of strings, and so it would be an over-generalization to supply them as free algorithms.
One way to counter that argument would be to identify the functions you have found useful on other containers, and to provide some use cases to buttress the argument.
Well, one thing I use it for is parsing HTTP directly in the read buffer, which is a vector. If the interfaces weren't generic, I'd either have to write my own functions to duplicate the functionality, or I'd have to copy the incoming data to a string. The first seems silly, and the latter would have unacceptable overhead in my case. The HTTP I'm parsing is streaming video from several dozen cameras at once, so I have to work with the buffers directly. I also use this library on plain old C strings, which wouldn't be possible if it were locked to basic_string. Some changes may make sense, but I really like the way it is now. -- Be seeing you.

I'm most disppointed to see that a more complete set of math functions has apparently been rejected for TR2. Like the interval library, this is something apparently obscure which could have widespread application - which is not going to have happen unless there the library exists. Chicken and egg problem ;-) This is still being worked on and I am still hopeful that we can produce an acceptable quality (if not the best) implementation for Boost based on the Cephes library. Paul Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539 561830 +44 7714 330204 mailto: pbristow@hetp.u-net.com www.hetp.u-net.com | -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of Beman Dawes | Sent: 10 October 2005 02:33 | To: boost@lists.boost.org | Cc: boost-users@lists.boost.org | Subject: [boost] Report from Mont Tremblant C++ Committee meeting | | The C++ Standards Committee met this past week in Mont | Tremblant, Quebec, | Canada. Many Boosters were present, and Boost continues to | get praise and | encouragement from non-Boost committee members. | | The Library Working Group (LWG) is starting serious work on | TR2. Initial | proposals for several Boost libraries were evaluated: | | Filesystem : Interested? Yes 17, No 0 | Date-Time : Interested? Yes 9, No 0 | Range : Want a C++03 version aimed at TR2, but still | interested in a | version based on new language features (Concepts perhaps?). | String-algo : Interested, but concern over interface and choice of | functions, generic vs basic_string.5.3 separate proposal | numeric_cast<> : Interested? Yes 10, No 0 | Interval : Interested? Yes 7, No 4. Concerns about | sufficiently large | user base to justify standardizing. | Optional : Interested? Strong yes 9, weak yes 2, weak no | 3, strong no 0 | Significant concerns about the interface: | Pointer interface. | Two ways of doing the same thing. | Depends on nullptr - is there a backup plan. | Dubious of use of references. | "Boost style" Threads : Pursue? Strong yes 9, weak yes 5, | weak no 0, strong | no 1 | | Also: | | minmax and / or algorithm std::minmax_element | In favor 13, Not in favor 0 | TR2 0 2 1 0 | C++0X 1 8 0 0 | Kevlin Henney Threads : Ask for fleshed-out proposal? Strong | yes 3, weak yes | 6, weak no 2, strong no 1 | | The next C++ Committee meeting will be in Berlin, Germany, | the first week of | April 2006. The meeting after that will be in Portland, | Oregon, US, in | October 2006. | | --Beman | | | | _______________________________________________ | Unsubscribe & other changes: | http://lists.boost.org/mailman/listinfo.cgi/boost |

Also of interest to Boosters... The C++ processor was brought into agreement with C99, meaning we now have Variadic macros, among other things, and the preprocessor library can start complaining about more bugs among the existing platforms! [although this is only against the working draught - a new standard is still a few years away] Also worth noting that Wave already implements most, if not all, the new features <g> -- AlisdairM Beman Dawes wrote:
The C++ Standards Committee met this past week in Mont Tremblant, Quebec, Canada. Many Boosters were present, and Boost continues to get praise and encouragement from non-Boost committee members.
The Library Working Group (LWG) is starting serious work on TR2. Initial proposals for several Boost libraries were evaluated:
Filesystem : Interested? Yes 17, No 0 Date-Time : Interested? Yes 9, No 0 Range : Want a C++03 version aimed at TR2, but still interested in a version based on new language features (Concepts perhaps?). String-algo : Interested, but concern over interface and choice of functions, generic vs basic_string.5.3 separate proposal numeric_cast<> : Interested? Yes 10, No 0 Interval : Interested? Yes 7, No 4. Concerns about sufficiently large user base to justify standardizing. Optional : Interested? Strong yes 9, weak yes 2, weak no 3, strong no 0 Significant concerns about the interface: Pointer interface. Two ways of doing the same thing. Depends on nullptr - is there a backup plan. Dubious of use of references. "Boost style" Threads : Pursue? Strong yes 9, weak yes 5, weak no 0, strong no 1
Also:
minmax and / or algorithm std::minmax_element In favor 13, Not in favor 0 TR2 0 2 1 0 C++0X 1 8 0 0 Kevlin Henney Threads : Ask for fleshed-out proposal? Strong yes 3, weak yes 6, weak no 2, strong no 1
The next C++ Committee meeting will be in Berlin, Germany, the first week of April 2006. The meeting after that will be in Portland, Oregon, US, in October 2006.

FWIW, I just posted 2 messages on comp.std.c++ were we can continue the optional<> discussions. See you there! Best -- Fernando Cacciola SciSoft http://fcacciola.50webs.com/
participants (34)
-
Aleksey Gurtovoy
-
Alisdair Meredith
-
AlisdairM
-
Anthony Williams
-
Beman Dawes
-
Brock Peabody
-
Daryle Walker
-
David Abrahams
-
Deane Yang
-
Eric Niebler
-
Fernando Cacciola
-
Hamish Mackenzie
-
Howard Hinnant
-
Ian McCulloch
-
Jaakko Jarvi
-
Jason Hise
-
Jeff Garland
-
Joe Gottman
-
Joel de Guzman
-
Keith MacDonald
-
Leo Goodstadt
-
Mat Marcus
-
Paul A Bristow
-
Peter Dimov
-
Reece Dunn
-
Rene Rivera
-
Rob Stewart
-
Sam Partington
-
Simon Buchan
-
Simon Richter
-
Thomas Witt
-
Thore Karlsen
-
Victor A. Wagner Jr.
-
Yuval Ronen