|  | Home | Libraries | People | FAQ | More | 
        Let's write and use a converter function that converts an a std::string
        to an int. It is possible that
        for a given string (e.g. "cat")
        there exist no value of type int
        capable of representing the conversion result. We do not consider such situation
        an error. We expect that the converter can be used only to check if the conversion
        is possible. A natural signature for this function can be:
      
#include <boost/optional.hpp> boost::optionl<int> convert(const std::string& text);
        All necessary functionality can be included with one header <boost/optional.hpp>.
        The above function signature means that the function can either return a
        value of type int or a flag
        indicating that no value of int
        is available. This does not indicate an error. It is like one additional
        value of int. This is how we
        can use our function:
      
const std::string& text = /*... */; boost::optionl<int> oi = convert(text); // move-construct if (oi) // contextual conversion to bool int i = *oi; // operator*
        In order to test if optional
        contains a value, we use the contextual conversion to type bool. Because of this we can combine the initialization
        of the optional object and the test into one instruction:
      
if (boost::optionl<int> oi = convert(text)) int i = *oi;
        We extract the contained value with operator* (and with operator-> where it makes sense). An attempt to
        extract the contained value of an uninitialized optional object is an undefined
        behaviour (UB). This implementation guards the call with BOOST_ASSERT. Therefore you should be sure
        that the contained value is there before extracting. For instance, the following
        code is reasonably UB-safe:
      
int i = *convert("100");
        This is because we know that string value "100"
        converts to a valid value of int.
        If you do not like this potential UB, you can use an alternative way of extracting
        the contained value:
      
try { int j = convert(text).value(); } catch (const boost::bad_optional_access&) { // deal with it }
        This version throws an exception upon an attempt to access a non-existent
        contained value. If your way of dealing with the missing value is to use
        some default, like 0, there exists
        a yet another alternative:
      
int k = convert(text).value_or(0);
        This uses the atoi-like approach
        to conversions: if text does
        not represent an integral number just return 0.
        Now, let's consider how function convert
        can be implemented.
      
boost::optionl<int> convert(const std::string& text) { std::stringstream s(text); int i; if ((s >> i) && s.get() == std::char_traits<char>::eof()) return i; else return boost::none; }
        Observe the two return statements. return
        i uses the converting constructor
        that can create optional<T>
        from T. Thus constructed
        optional object is initialized and its value is a copy of i.
        The other return statement uses another converting constructor from a special
        tag boost::none. It is used to indicate that we want
        to create an uninitialized optional object.