|
Boost : |
From: Mat Marcus (mmarcus-boost_at_[hidden])
Date: 2003-08-31 02:34:39
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk