In this post I will put forward a use-case or two to help see whether something a little different then the current version of optional might be useful. I also begin making a case that a Concept like PossiblyUninitializedVariable might be more generally useful than OptionalPointee. As I mentioned in the post that started this thread, I am writing a library that makes heavy use of using boost::graph and boost::tie. In the implementation of my library there is plenty of code that looks like this:
//... typedef /*details ommitted*/ Iter; typedef /*details ommitted*/ Vertex; typedef /*details ommitted*/ Graph;
std::pair<Iter, Iter> out_edges(Vertex, Graph); //...
Iter begin, end; Graph g(/*...*/); //... boost::tie(begin, end) = out_edges(v,g);
It bothers me somewhat that begin and end are sitting there in an (implicitly) uninitialized state. Maybe during later maintenance of this code a new control path could get added and begin or end might be used without first being set. So I thought I'd try to see whether I could make the code more robust using boost::optional. I imagined following a convention along the lines of "Initialize all local variables where declared, or when that is impossible use optional to protect against their inadvertent uninitialized use". But it turns out the optional doesn't really work with tie. Here's what I thought would be possible:
//... same as first version typedef /*details ommitted*/ Iter; typedef /*details ommitted*/ Vertex; typedef /*details ommitted*/ Graph;
std::pair<Iter, Iter> out_edges(Vertex, Graph); //...
boost::optional<Iter> begin, end; //now use optional Graph g(/*...*/); //... boost::tie(begin, end) = out_edges(v,g); //sorry, doesn't work
After reading the documentation more carefully I learned that optional models pointer behavior. I spelled out how the code might look:
boost::tie(*begin, *end); //sorry, ASSERT && looks too strange
Wow, that looked strange to me. I don't think of begin and end as pointers at all here. I just want to model values that haven't been initialized, and I maintain that initialized/unintialized is the concept worth modeling (I'm not sure what its name ought to be, so for now I'll just refer to it as the PossiblyUninitialized Concept). Such a concept might perhpaps embody notions of initialization via construction or assignment, testing whether the model has been initialized, etc. It may (or may not) also be true that there is some use in thinking of pointer/NULL as model of PossiblyUnintialized variables, but seems to me that the current version of optional has it backwards: I don't want to model all cases of possibly unininitialized behavior as OptionalPointees.
So here's my wishlist for an optional-like facility:
* I want instances to model PossiblyUninitialized (not OptionalPointee), e.g. optional sans pointer interface. * It want to be able to write functions that accept PossiblyUninitialized variables as parameters. But I want it to be easy for clients to call such routines with intialized values. That is I want to write:
void foo(optional<Bar>); //... Bar b(/*details ommitted*/); foo(b); // Ok: passing in a valid Bar foo(optional<Bar>()); //Also ok, passing in uninitialized Bar
This was one reason why I speculated that implicit construction might be useful here.
* I want to be able to use optional and tie together as in the beginning of this post or pssibly using some additional syntax:
tie(begin.uninitialized_ref(), end.uninitialized_ref()) = //...
if I really have to.
It may be that some of these wishes are ill-concevied or impractical. But the fact that optional models OptionalPointee instead of something like PossiblyUnitinitialized leaves me looking for alternatives, especially if that's what is preventing me from having other items on my wish list.
- Mat _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost