When to use boost::Optional?
boost::optional
- Class template optional is a wrapper for representing ‘optional’ (or ‘nullable’) objects who may not (yet) contain a valid value.
- Introduced and supported from C++17 in std::optional (defined in header
<optional>
) - Supported in code by including
#include <boost/optional.hpp>
It is recommended to use optional
in situations where there is exactly one, clear (to all parties) reason for having no value of type T, and where the lack of value is as natural as having any regular value of T. - Empty return data value
#include<iostream>
#include<fstream>
std::string ReadFileAsString(const std::string& filepath) {
std::ifstream stream(filepath);
if(stream) {
std::string res;
//read file
stream.close();
return res;
}
return std::string(); // return ""; --> empty string
}
int main() {
std::string data = ReadFileAsString("data.txt");
if(data != "") //
{
}
}
- Utilize optional to deal with no value data
#include<iostream>
#include<fstream>
#include<optional> //introduced in c++17
std::optional<std::string> ReadFileAsString(const std::string& filepath) {
std::ifstream stream(filepath);
if(stream) {
std::string res;
//read file
stream.close();
return res;
}
return {}; // return ""; --> empty string
}
int main() {
std::optional<std::string> data = ReadFileAsString("data.txt");
std::string value = data.value_or("Not present");
if(data.has_value()) //if(data) --> is okay
{
//optional has been set
cout << data.value();
}
else
{
//optional has not been set
}
}
- value_or
- if the data is present, it will return to us the value
- if the data is not set, it will return whatever value parsed in
HERE
.- value_or(“HERE”);
- usually default value is set in
HERE
boost::make_optionl
optional<T (not a ref)> make_optional( T const& v )
optional<T (not a ref)> make_optional( bool condition, T const& v )
- Returns: optional
(v) for the deduced type T of v. -
Returns: optional
(condition,v) for the deduced type T of v. - Example 1
- when using make_optional - can utilize condition
- Creates an optional
initialized with 'val' IFF cond is true, otherwise creates an `uninitialized optional`
#include "boost/optional/optional.hpp" // boost/none.hpp is included automatically
boost::optional<int> foo ( int a )
{
return some_condition(a) ? boost::make_optional(a) : boost::none ;
// NOTE: in real code you can just use this: make_optional(some_condition(a), a)
}
- defined code
typedef optional_detail::optional_base<T> base ;
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
:
m_initialized(false)
{
if ( cond )
construct(val);
}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
// Returns optional<T>(cond,v)
template<class T>
inline
optional<T> make_optional ( bool cond, T const& v )
{
return optional<T>(cond,v);
}
uninitialized optional
- uninitialized optional
- In C++ there is no formal notion of uninitialized objects, which means that objects always have an initial value even if indeterminate. As discussed on the previous section, this has a drawback because you need additional information to tell if an object has been effectively initialized. One of the typical ways in which this has been historically dealt with is via a special value: EOF,npos,-1, etc… This is equivalent to adding the special value to the set of possible values of a given type.
- when a variable is declared as optional
and no initial value is given, the variable is formally uninitialized. A formally uninitialized optional object has conceptually no value at all and this situation can be tested at runtime. It is formally undefined behavior to try to access the value of an uninitialized optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal treatment of initialization states in optional objects, it is even possible to reset an optional to uninitialized. boost::none
namespace boost {
class none_t {/* see below */};
const none_t none (/* see below */);
} // namespace boost
optional
Starting with Boost version 1.34.0, both boost::none_t
and boost::none
are included in boost/none.hpp
, which is automatically included by boost/optional/optional.hpp
This contant is similar in purpose to NULL, except that is not a null pointer value
. You can use it to initialize an optional