| Home | Libraries | People | FAQ | More

#### Detailed Semantics - Optional Values

| 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.

> `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 ) ;

> `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 ) ;

> `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 ) ;

> `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 ) ;

> `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()`

> `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 ) ;

> `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) ) ;

> `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 ) ;

> `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 ) ;

> `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());

> `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);

> `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 ) ;

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

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

> `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 ) ;

> `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 ) ;

> `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'.

> `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) ) ;

> `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) ) ;

> `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) ) ;

> `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)

> `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.

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

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

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

- Deprecated: Same as `operator=( none_t );`

> `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()`.

> `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 ) ;

> `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.

> `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 );
      }

> `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.

> `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&`.

> `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.

> `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);

> `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.

> `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 ) ;

> `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) ) ;

> `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 ;

> `explicit optional<T>::operator bool() 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 );

> `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 ) ;

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

- Deprecated: Same as `explicit operator bool () ;`