Boost logo

Boost :

From: Gennadiy E. Rozental (rogeeff_at_[hidden])
Date: 2001-08-28 13:59:36


Hi,

I was interested in a proposed idea when you posted it. But I was not
pleased with pointer sematic proposed for the class optional
(statefull). The main point is that optional should cost as less as
possible. So no additinal dereferensing should be present. Idea with
runtime exception is also unclear. How do you imagine somebody would
use it?

   optional<T> t = foo();

   try {
    ...
      use *t
   }
   catch( runtime exception ) {
      do error processing
   }

Instead it could be wirtten like this

   optional<T> t = foo();

   if( !t ) {
      do error processing
   }
   else {
      use *t
   }

But the original idea seems good, so I designed different class
optional. I allowed myself to define operator* just to shorten code
when used:
(sorry alignment a little bit drift)

#ifndef OPTIONAL_HPP
#define OPTIONAL_HPP

namespace boost {

// Models a variable which has an associated 'm_initialized' state.
// A default constructed instance of optional<T> is uninitialized.
// An non-default constructed instance of optional<T> is initialized.
//

template<typename T>
class optional;

namespace detail {

template<typename T>
class value_proxy {
public:
    explicit value_proxy( optional<T>& opt ) : m_opt(opt) {}

    operator T const&() const { return m_opt.value(); }
    optional<T>& operator=( T const& arg ) const;

private:
    optional<T>& m_opt;
};

} // namespace detail

template<typename T>
class optional {
public :
    typedef T value_type;

    // Constructors, allows implicit conversion
    optional()
    : m_initialized( false ) {}
    optional( const T& _v )
    : m_v( _v ), m_initialized( true ){}
    optional( const optional& rhs )
    : m_v( rhs.m_v ), m_initialized(rhs.m_initialized) {}

    // Assignment operators
    optional& operator=( const optional& rhs ) {
        try {
            if( rhs.m_initialized )
                m_v = rhs.m_v;
            m_initialized = rhs.m_initialized;
        }
        catch( ... ) {
            m_initialized = false;
            throw;
        }

        return *this;
    }
    optional& operator=( const T& rhs ){
         return operator=( optional( rhs ) );
    }

    // Value access
    T const& value() const { return m_v; }
    T& value () { return m_v; }
    T const& operator*() const { return value(); }
    detail::value_proxy<T> operator*() {
       return detail::value_proxy<T>( *this );
    }

    // Is initialized checks
    bool initialized() const { return m_initialized; }
    bool operator!() const { return !initialized(); }
    operator bool() const { return initialized(); }

    // Comparison operators
    friend bool operator==( const optional& lhs, const optional&
rhs ) { return lhs.compare( rhs.get() ); }
    friend bool operator!=( const optional& lhs, const optional&
rhs ) { return !lhs.compare( rhs.get() ); }
    friend bool operator==( const optional& lhs, const T&
rhs ) { return lhs.compare( rhs ); }
    friend bool operator!=( const optional& lhs, const T&
rhs ) { return !lhs.compare( rhs ); }
    friend bool operator==( const T& lhs, const optional&
rhs ) { return rhs.compare( lhs ); }
    friend bool operator!=( const T& lhs, const optional&
rhs ) { return !rhs.compare( lhs ); }

private:
    // Comparison helper
    bool compare( const T& rhs ) const {
        return m_initialized ? m_v == rhs : false;
    }

    // Data members
    T m_v;
    bool m_initialized;
};

template<typename T>
inline optional<T>&
detail::value_proxy<T>::operator=( T const& arg ) const {
    m_opt = arg;
    
    return m_opt;
}

} // namespace boost

#endif // OPTIONAL_HPP

/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////

This is an alternative. What do you think?

Gennadiy.

--- In boost_at_y..., "Fernando Cacciola" <fcacciola_at_g...> wrote:
> Hi everyone.
>
> Though I haven't draw much attention with this class last time I
tried, I
> cleaned it up a little: changed its name to optional<> and made the
semantic
> more consistent.
> I uploaded a fully documented optional.hpp and optional_test.cpp
>
> It's in the Files Section, under the folder 'class optional':
>
> http://groups.yahoo.com/group/boost/files/class%20optional/
>
> Please do take a look at it, I would like to have this submitted
for formal
> review.
> (At least, let me know if the trick I used to remove the
requirement of
> default-constructible is appropriate)
>
> Thanks,
>
> Fernando Cacciola
> Sierra s.r.l.
> fcacciola_at_g...
> www.gosierra.com


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