Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2002-12-10 10:43:01


OK, I've been thinking about the interface a bit more and want to voice
some other opinions. First, why were pointer semantics chosen at all?
Why couldn't you have gone with value semantics?

optional<int> foo()
{
   //...
}

void bar(int value)
{
   //...
}

optional<int> res = foo();
if (res.initialized())
   bar(res);

I can think of a few reasons, but want to hear about them from the
designer, and want to see the rationale documented.

Now, assuming we stick with pointer semantics, let's make this as close to
the "normal" smart pointer interface as possible:

template <typename T>
class optional
{
public:
   optional();
   explicit optional(T const& value);
   optional(optional const& other);
   template <typename U>
      optional(optional<U> const& other);
   ~optional();

   T& operator*() const;
   T* operator->() const;
   T* get() const;
   // T* release();
   void reset();
   void reset(T const& value);
   operator unspecified-bool-type() const;
};

Semantics and rationale:

optional()

   Constructs an "uninitialized" optional.

explicit optional(T const& value)

   Constructs an optional initialized to value through copy construction.

optional(optional const& other)

   Copy constructs an optional using the value-type's copy constructor.

template <typename U> optional(optional<U> const& other)

   Allows copy construction from "compatible" optionals (optionals with
value types that can be used for constructing this optional's value
type). I'm not sure how important this one is for optional, to be
honest.

~optional()

   If the optional is initialized, calls the value-type's destructor.

T& operator*() const

   If the optional is not initialized, results in undefined behavior.
Otherwise, returns a reference to the value.

T* operator->() const

   If the optional is not initialized, results in undefined behavior.

T* get() const

   If the optional is not initialized, returns 0. Otherwise, returns a
pointer to the value.

   Rationale: This provides the interface to determine whether or not the
optional has been initialized. Nothing else is required.

// T* release()

   Rationale: Since ownership can not be transferred, this interface is
not supported.

void reset()

   If the optional is initialized, calls the destructor and sets the
optional as "uninitialized".

   Rationale: Provides an interface to put the optional back into an
"uninitialized" state.

void reset(T const& other)

   If the optional is initialized, calls the destructor. Copy constructs
the value in place.

   Rationale: Provides an interface to set the value for an optional in
an "uninitialized" state. If there's some meta-magic that would allow
you to use the value's operator=() if it has one this could be used as
an optimization instead of the destruct/construct idiom.

operator unspecified-bool-type() const

   Returns an unspecified type (safe-bool idiom) that's convertable to
bool, with a true value indicating the optional is not in an
uninitialized state.

   Rationale: Allows for easier testing for the "uninitialized" state,
especially for testing through assignments:

   if (opt = foo())

This interface is nearly identical to std::auto_ptr, and as such should be
instantly understandable by most C++ programmers. It provides all of the
functionality present in the currently proposed interface, yet doesn't
provide unnecessary duplicate interfaces or any use cases that should be
ambiguous.

William E. Kempf


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