Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Detailed Semantics - Optional Values
PrevUpHomeNext
[Note] Note

The following section contains various assert() which are used only to show the postconditions as sample code. It is not implied that the type T must support each particular expression but that if the expression is supported, the implied condition holds.

space

optional<T>::optional() noexcept;

  • Effect: Default-Constructs an optional.
  • Postconditions: *this is uninitialized.
  • Notes: T's default constructor is not called.
  • Example:
    optional<T> def ;
    assert ( !def ) ;
    

space

optional<T>::optional( none_t ) noexcept;

  • Effect: Constructs an optional uninitialized.
  • Postconditions: *this is uninitialized.
  • Notes: T's default constructor is not called. The expression boost::none denotes an instance of boost::none_t that can be used as the parameter.
  • Example:
    #include <boost/none.hpp>
    optional<T> n(none) ;
    assert ( !n ) ;
    

space

optional<T>::optional( T const& v )

  • Requires: is_copy_constructible<T>::value is true.
  • Effect: Directly-Constructs an optional.
  • Postconditions: *this is initialized and its value is a copy of v.
  • Throws: Whatever T::T( T const& ) throws.
  • Notes: T::T( T const& ) is called.
  • Exception Safety: Exceptions can only be thrown during T::T( T const& ); in that case, this constructor has no effect.
  • Example:
    T v;
    optional<T> opt(v);
    assert ( *opt == v ) ;
    

space

optional<T>::optional( T&& v )

  • Requires: is_move_constructible<T>::value is true.
  • Effect: Directly-Move-Constructs an optional.
  • Postconditions: *this is initialized and its value is move-constructed from v.
  • Throws: Whatever T::T( T&& ) throws.
  • Notes: T::T( T&& ) is called.
  • Exception Safety: Exceptions can only be thrown during T::T( T&& ); in that case, the state of v is determined by exception safety guarantees for T::T(T&&).
  • Example:
    T v1, v2;
    optional<T> opt(std::move(v1));
    assert ( *opt == v2 ) ;
    

space

optional<T>::optional( bool condition, T const& v ) ;

  • If condition is true, same as:

optional<T>::optional( T const& v )

  • otherwise, same as:

optional<T>::optional()

space

optional<T>::optional( optional const& rhs );

  • Requires: is_copy_constructible<T>::value is true.
  • Effect: Copy-Constructs an optional.
  • Postconditions: If rhs is initialized, *this is initialized and its value is a copy of the value of rhs; else *this is uninitialized.
  • Throws: Whatever T::T( T const& ) throws.
  • Notes: If rhs is initialized, T::T(T const& ) is called.
  • Exception Safety: Exceptions can only be thrown during T::T( T const& ); in that case, this constructor has no effect.
  • Example:
    optional<T> uninit ;
    assert (!uninit);
    
    optional<T> uinit2 ( uninit ) ;
    assert ( uninit2 == uninit );
    
    optional<T> init( T(2) );
    assert ( *init == T(2) ) ;
    
    optional<T> init2 ( init ) ;
    assert ( init2 == init ) ;
    

space

optional<T>::optional( optional&& rhs ) noexcept(see below);

  • Requires: is_move_constructible<T>::value is true.
  • Effect: Move-constructs an optional.
  • Postconditions: If rhs is initialized, *this is initialized and its value is move constructed from rhs; else *this is uninitialized.
  • Throws: Whatever T::T( T&& ) throws.
  • Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value.
  • Notes: If rhs is initialized, T::T( T && ) is called.
  • Exception Safety: Exceptions can only be thrown during T::T( T&& ); in that case, rhs remains initialized and the value of *rhs is determined by exception safety of T::T(T&&).
  • Example:
    optional<std::unique_ptr<T>> uninit ;
    assert (!uninit);
    
    optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    assert ( uninit2 == uninit );
    
    optional<std::unique_ptr<T>> init( std::uniqye_ptr<T>(new T(2)) );
    assert ( **init == T(2) ) ;
    
    optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    assert ( init );
    assert ( *init == nullptr );
    assert ( init2 );
    assert ( **init2 == T(2) ) ;
    

space

template<U> explicit optional<T>::optional( optional<U> const& rhs );

  • Effect: Copy-Constructs an optional.
  • Postconditions: If rhs is initialized, *this is initialized and its value is a copy of the value of rhs converted to type T; else *this is uninitialized.
  • Throws: Whatever T::T( U const& ) throws.
  • Notes: T::T( U const& ) is called if rhs is initialized, which requires a valid conversion from U to T.
  • Exception Safety: Exceptions can only be thrown during T::T( U const& ); in that case, this constructor has no effect.
  • Example:
    optional<double> x(123.4);
    assert ( *x == 123.4 ) ;
    
    optional<int> y(x) ;
    assert( *y == 123 ) ;
    

space

template<U> explicit optional<T>::optional( optional<U>&& rhs );

  • Effect: Move-constructs an optional.
  • Postconditions: If rhs is initialized, *this is initialized and its value is move-constructed from *rhs; else *this is uninitialized.
  • Throws: Whatever T::T( U&& ) throws.
  • Notes: T::T( U&& ) is called if rhs is initialized, which requires a valid conversion from U to T.
  • Exception Safety: Exceptions can only be thrown during T::T( U&& ); in that case, rhs remains initialized and the value of *rhs is determined by exception safety guarantee of T::T( U&& ).
  • Example:
    optional<double> x(123.4);
    assert ( *x == 123.4 ) ;
    
    optional<int> y(std::move(x)) ;
    assert( *y == 123 ) ;
    

space

template<class... Args> explicit optional<T>::optional( in_place_init_t, Args&&... ars );

  • Requires: is_constructible_v<T, Args&&...> is true.
  • Effect: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
  • Postconditions: *this is initialized.
  • Throws: Any exception thrown by the selected constructor of T.
  • Notes: T need not be MoveConstructible. On compilers that do not suppor variadic templates or rvalue references, this constuctor is available in limited functionality. For details see here.
  • Example:
    // creates an std::mutex using its default constructor
    optional<std::mutex> om {in_place_init};
    assert (om);
    
    // creates a unique_lock by calling unique_lock(*om, std::defer_lock)
    optional<std::unique_lock<std::mutex>> ol {in_place_init, *om, std::defer_lock};
    assert (ol);
    assert (!ol->owns_lock());
    

space

template<class... Args> explicit optional<T>::optional( in_place_init_if_t, bool condition, Args&&... ars );

  • Requires: is_constructible_v<T, Args&&...> is true.
  • Effect: If condition is true, initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
  • Postconditions: bool(*this) == condition.
  • Throws: Any exception thrown by the selected constructor of T.
  • Notes: T need not be MoveConstructible. On compilers that do not suppor variadic templates or rvalue references, this constuctor is available in limited functionality. For details see here.
  • Example:
    optional<std::vector<std::string>> ov1 {in_place_init_if, false, 3, "A"};
    assert (!ov1);
    
    optional<std::vector<std::string>> ov2 {in_place_init_if, true, 3, "A"};
    assert (ov2);
    assert (ov2->size() == 3);
    

space

template<InPlaceFactory> explicit optional<T>::optional( InPlaceFactory const& f );

template<TypedInPlaceFactory> explicit optional<T>::optional( TypedInPlaceFactory const& f );

  • Effect: Constructs an optional with a value of T obtained from the factory.
  • Postconditions: *this is initialized and its value is directly given from the factory f (i.e., the value is not copied).
  • Throws: Whatever the T constructor called by the factory throws.
  • Notes: See In-Place Factories
  • Exception Safety: Exceptions can only be thrown during the call to the T constructor used by the factory; in that case, this constructor has no effect.
  • Example:
    class C { C ( char, double, std::string ) ; } ;
    
    C v('A',123.4,"hello");
    
    optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    
    assert ( *x == v ) ;
    assert ( *y == v ) ;
    

space

optional& optional<T>::operator= ( none_t ) noexcept;

  • Effect: If *this is initialized destroys its contained value.
  • Postconditions: *this is uninitialized.

space

optional& optional<T>::operator= ( T const& rhs ) ;

  • Effect: Assigns the value rhs to an optional.
  • Postconditions: *this is initialized and its value is a copy of rhs.
  • Throws: Whatever T::operator=( T const& ) or T::T(T const&) throws.
  • Notes: If *this was initialized, T's assignment operator is used, otherwise, its copy-constructor is used.
  • Exception Safety: In the event of an exception, the initialization state of *this is unchanged and its value unspecified as far as optional is concerned (it is up to T's operator=()). If *this is initially uninitialized and T's copy constructor fails, *this is left properly uninitialized.
  • Example:
    T x;
    optional<T> def ;
    optional<T> opt(x) ;
    
    T y;
    def = y ;
    assert ( *def == y ) ;
    opt = y ;
    assert ( *opt == y ) ;
    

space

optional& optional<T>::operator= ( T&& rhs ) ;

  • Effect: Moves the value rhs to an optional.
  • Postconditions: *this is initialized and its value is moved from rhs.
  • Throws: Whatever T::operator=( T&& ) or T::T(T &&) throws.
  • Notes: If *this was initialized, T's move-assignment operator is used, otherwise, its move-constructor is used.
  • Exception Safety: In the event of an exception, the initialization state of *this is unchanged and its value unspecified as far as optional is concerned (it is up to T's operator=()). If *this is initially uninitialized and T's move constructor fails, *this is left properly uninitialized.
  • Example:
    T x;
    optional<T> def ;
    optional<T> opt(x) ;
    
    T y1, y2, yR;
    def = std::move(y1) ;
    assert ( *def == yR ) ;
    opt = std::move(y2) ;
    assert ( *opt == yR ) ;
    

space

optional& optional<T>::operator= ( optional const& rhs ) ;

  • Requires: T is CopyConstructible and CopyAssignable.
  • Effects:

    *this contains a value

    *this does not contain a value

    rhs contains a value

    assigns *rhs to the contained value

    initializes the contained value as if direct-initializing an object of type T with *rhs

    rhs does not contain a value

    destroys the contained value by calling val->T::~T()

    no effect

  • Returns: *this;
  • Postconditions: bool(rhs) == bool(*this).
  • Exception Safety: If any exception is thrown, the initialization state of *this and rhs remains unchanged. If an exception is thrown during the call to T's copy constructor, no effect. If an exception is thrown during the call to T's copy assignment, the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
  • Example:
    T v;
    optional<T> opt(v);
    optional<T> def ;
    
    opt = def ;
    assert ( !def ) ;
    // previous value (copy of 'v') destroyed from within 'opt'.
    

space

optional& optional<T>::operator= ( optional&& rhs ) noexcept(see below);

  • Requires: T is MoveConstructible and MoveAssignable.
  • Effects:

    *this contains a value

    *this does not contain a value

    rhs contains a value

    assigns std::move(*rhs) to the contained value

    initializes the contained value as if direct-initializing an object of type T with std::move(*rhs)

    rhs does not contain a value

    destroys the contained value by calling val->T::~T()

    no effect

  • Returns: *this;
  • Postconditions: bool(rhs) == bool(*this).
  • Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value.
  • Exception Safety: If any exception is thrown, the initialization state of *this and rhs remains unchanged. If an exception is thrown during the call to T's move constructor, the state of *rhs is determined by the exception safety guarantee of T's move constructor. If an exception is thrown during the call to T's move-assignment, the state of **this and *rhs is determined by the exception safety guarantee of T's move assignment.
  • Example:
    optional<T> opt(T(2)) ;
    optional<T> def ;
    
    opt = def ;
    assert ( def ) ;
    assert ( opt ) ;
    assert ( *opt == T(2) ) ;
    

space

template<U> optional& optional<T>::operator= ( optional<U> const& rhs ) ;

  • Effect:

    *this contains a value

    *this does not contain a value

    rhs contains a value

    assigns *rhs to the contained value

    initializes the contained value as if direct-initializing an object of type T with *rhs

    rhs does not contain a value

    destroys the contained value by calling val->T::~T()

    no effect

  • Returns: *this.
  • Postconditions: bool(rhs) == bool(*this).
  • Exception Safety: If any exception is thrown, the result of the expression bool(*this) remains unchanged. If an exception is thrown during the call to T's constructor, no effect. If an exception is thrown during the call to T's assignment, the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
  • Example:
    T v;
    optional<T> opt0(v);
    optional<U> opt1;
    
    opt1 = opt0 ;
    assert ( *opt1 == static_cast<U>(v) ) ;
    

space

template<U> optional& optional<T>::operator= ( optional<U>&& rhs ) ;

  • Effect:

    *this contains a value

    *this does not contain a value

    rhs contains a value

    assigns std::move(*rhs) to the contained value

    initializes the contained value as if direct-initializing an object of type T with std::move(*rhs)

    rhs does not contain a value

    destroys the contained value by calling val->T::~T()

    no effect

  • Returns: *this.
  • Postconditions: bool(rhs) == bool(*this).
  • Exception Safety: If any exception is thrown, the result of the expression bool(*this) remains unchanged. If an exception is thrown during the call to T's constructor, no effect. If an exception is thrown during the call to T's assignment, the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
  • Example:
    T v;
    optional<T> opt0(v);
    optional<U> opt1;
    
    opt1 = std::move(opt0) ;
    assert ( opt0 );
    assert ( opt1 )
    assert ( *opt1 == static_cast<U>(v) ) ;
    

space

template<class... Args> void optional<T>::emplace( Args&&... args );

  • Requires: The compiler supports rvalue references and variadic templates.
  • Effect: If *this is initialized calls *this = none. Then initializes in-place the contained value as if direct-initializing an object of type T with std::forward<Args>(args)....
  • Postconditions: *this is initialized.
  • Throws: Whatever the selected T's constructor throws.
  • Exception Safety: If an exception is thrown during the initialization of T, *this is uninitialized.
  • Notes: T need not be MoveConstructible or MoveAssignable. On compilers that do not suppor variadic templates or rvalue references, this function is available in limited functionality. For details see here.
  • Example:
    T v;
    optional<const T> opt;
    opt.emplace(0);  // create in-place using ctor T(int)
    opt.emplace();   // destroy previous and default-construct another T
    opt.emplace(v);  // destroy and copy-construct in-place (no assignment called)
    

space

template<InPlaceFactory> optional<T>& optional<T>::operator=( InPlaceFactory const& f );

template<TypedInPlaceFactory> optional<T>& optional<T>::operator=( TypedInPlaceFactory const& f );

  • Effect: Assigns an optional with a value of T obtained from the factory.
  • Postconditions: *this is initialized and its value is directly given from the factory f (i.e., the value is not copied).
  • Throws: Whatever the T constructor called by the factory throws.
  • Notes: See In-Place Factories
  • Exception Safety: Exceptions can only be thrown during the call to the T constructor used by the factory; in that case, the optional object will be reset to be uninitialized.

space

void optional<T>::reset( T const& v ) ;

  • Deprecated: same as operator= ( T const& v) ;

space

void optional<T>::reset() noexcept ;

  • Effects: Same as operator=( none_t );

space

T const& optional<T>::get() const ;

T& optional<T>::get() ;

inline T const& get ( optional<T> const& ) ;

inline T& get ( optional<T> &) ;

  • Requires: *this is initialized
  • Returns: A reference to the contained value
  • Throws: Nothing.
  • Notes: The requirement is asserted via BOOST_ASSERT().

space

T const& optional<T>::operator*() const& ;

T& optional<T>::operator*() &;

  • Requires: *this is initialized
  • Returns: A reference to the contained value
  • Throws: Nothing.
  • Notes: The requirement is asserted via BOOST_ASSERT(). On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a const and non-const member functions.
  • Example:
    T v ;
    optional<T> opt ( v );
    T const& u = *opt;
    assert ( u == v ) ;
    T w ;
    *opt = w ;
    assert ( *opt == w ) ;
    

space

T&& optional<T>::operator*() &&;

  • Requires: *this contains a value.
  • Effects: Equivalent to return std::move(*val);.
  • Notes: The requirement is asserted via BOOST_ASSERT(). On compilers that do not support ref-qualifiers on member functions this overload is not present.

space

T const& optional<T>::value() const& ;

T& optional<T>::value() & ;

  • Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();.
  • Notes: On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a const and non-const member functions.
  • Example:
    T v ;
    optional<T> o0, o1 ( v );
    assert ( o1.value() == v );
    
    try {
      o0.value(); // throws
      assert ( false );
    }
    catch(bad_optional_access&) {
      assert ( true );
    }
    

space

T&& optional<T>::value() && ;

  • Effects: Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();.
  • Notes: On compilers that do not support ref-qualifiers on member functions this overload is not present.

space

template<class U> T optional<T>::value_or(U && v) const& ;

  • Effects: Equivalent to if (*this) return **this; else return std::forward<U>(v);.
  • Remarks: If T is not CopyConstructible or U && is not convertible to T, the program is ill-formed.
  • Notes: On compilers that do not support ref-qualifiers on member functions this overload is replaced with the const-qualified member function. On compilers without rvalue reference support the type of v becomes U const&.

space

template<class U> T optional<T>::value_or(U && v) && ;

  • Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);.
  • Remarks: If T is not MoveConstructible or U && is not convertible to T, the program is ill-formed.
  • Notes: On compilers that do not support ref-qualifiers on member functions this overload is not present.

space

template<class F> T optional<T>::value_or_eval(F f) const& ;

  • Requires: T is CopyConstructible and F models a Generator whose result type is convertible to T.
  • Effects: if (*this) return **this; else return f();.
  • Notes: On compilers that do not support ref-qualifiers on member functions this overload is replaced with the const-qualified member function.
  • Example:
    int complain_and_0()
    {
      clog << "no value returned, using default" << endl;
      return 0;
    }
    
    optional<int> o1 = 1;
    optional<int> oN = none;
    
    int i = o1.value_or_eval(complain_and_0); // fun not called
    assert (i == 1);
    
    int j = oN.value_or_eval(complain_and_0); // fun called
    assert (i == 0);
    

space

template<class F> T optional<T>::value_or_eval(F f) && ;

  • Requires: T is MoveConstructible and F models a Generator whose result type is convertible to T.
  • Effects: if (*this) return std::move(**this); else return f();.
  • Notes: On compilers that do not support ref-qualifiers on member functions this overload is not present.

space

template<class F> auto optional<T>::map(F f) const& -> see below ;

template<class F> auto optional<T>::map(F f) & -> see below ;

  • Effects: if (*this) return f(**this); else return none;
  • Notes: The return type of these overloads is optional<decltype(f(**this))>. On compilers that do not support ref-qualifiers on member functions, these two (as well as the next one) overloads are replaced with good old const and non-const overloads.
  • Example:
    auto length = [](const string& s){ return s.size(); };
    optional<string> o1 {}, o2 {"cat"};
    optional<size_t> os1 = o1.map(length), os2 = o2.map(length);
    assert ( !os1 ) ;
    assert ( os2 ) ;
    assert ( *os2 == 3 ) ;
    

space

template<class F> auto optional<T>::map(F f) && -> see below ;

  • Effects: if (*this) return f(std::move(**this)); else return none;
  • Notes: The return type of this overload is optional<decltype(f(istd::move(**this)))>.

space

template<class F> auto optional<T>::flat_map(F f) const& -> see below ;

template<class F> auto optional<T>::flat_map(F f) & -> see below ;

  • Requires: The return type of expression f(**this) is optional<U> for some object or reference type U.
  • Effects: if (*this) return f(**this); else return none;
  • Notes: The return type of these overloads is optional<U>. On compilers that do not support ref-qualifiers on member functions, these two (as well as the next one) overloads are replaced with good old const and non-const overloads.
  • Example:
    optional<char> first_char(const string& s) {
      return s.empty() ? none : optional<char>(s[0]);
    };
    optional<string> o1 {}, o2 {"cat"};
    optional<char> os1 = o1.flat_map(first_char), os2 = o2.flat_map(first_char);
    assert ( !os1 ) ;
    assert ( os2 ) ;
    assert ( *os2 == 'c' ) ;
    
    space

template<class F> auto optional<T>::flat_map(F f) && -> see below ;

  • Requires: The return type of expression f(std::move(**this)) is optional<U> for some object or reference type U.
  • Effects: if (*this) return f(std::move(**this)); else return none;
  • Notes: The return type of this overload is optional<U>.

space

T const& optional<T>::get_value_or( T const& default) const ;

T& optional<T>::get_value_or( T& default ) ;

  • Deprecated: Use value_or() instead.
  • Returns: A reference to the contained value, if any, or default.
  • Throws: Nothing.
  • Example:
    T v, z ;
    optional<T> def;
    T const& y = def.get_value_or(z);
    assert ( y == z ) ;
    
    optional<T> opt ( v );
    T const& u = opt.get_value_or(z);
    assert ( u == v ) ;
    assert ( u != z ) ;
    

space

T const* optional<T>::get_ptr() const ;

T* optional<T>::get_ptr() ;

  • Returns: If *this is initialized, a pointer to the contained value; else 0 (null).
  • Throws: Nothing.
  • Notes: The contained value is permanently stored within *this, so you should not hold nor delete this pointer
  • Example:
    T v;
    optional<T> opt(v);
    optional<T> const copt(v);
    T* p = opt.get_ptr() ;
    T const* cp = copt.get_ptr();
    assert ( p == get_pointer(opt) );
    assert ( cp == get_pointer(copt) ) ;
    

space

T const* optional<T>::operator ->() const ;

T* optional<T>::operator ->() ;

  • Requires: *this is initialized.
  • Returns: A pointer to the contained value.
  • Throws: Nothing.
  • Notes: The requirement is asserted via BOOST_ASSERT().
  • Example:
    struct X { int mdata ; } ;
    X x ;
    optional<X> opt (x);
    opt->mdata = 2 ;
    

space

explicit optional<T>::operator bool() const noexcept ;

bool optional<T>::has_value() const noexcept ;

  • Returns: get_ptr() != 0.
  • Notes: On compilers that do not support explicit conversion operators this falls back to safe-bool idiom.
  • Example:
    optional<T> def ;
    assert ( def == 0 );
    optional<T> opt ( v ) ;
    assert ( opt );
    assert ( opt != 0 );
    

space

bool optional<T>::operator!() noexcept ;

  • Returns: If *this is uninitialized, true; else false.
  • Notes: This operator is provided for those compilers which can't use the unspecified-bool-type operator in certain boolean contexts.
  • Example:
    optional<T> opt ;
    assert ( !opt );
    *opt = some_T ;
    
    // Notice the "double-bang" idiom here.
    assert ( !!opt ) ;
    

space

bool optional<T>::is_initialized() const ;

  • Deprecated: Same as explicit operator bool () ;

PrevUpHomeNext