estd::optional
Overview
estd::optional
is a wrapper representing a value that may or not be valid,
that adds an additional possible value to the wrapped type. This can be used to
represent an invalid or empty state.
The instance of the wrapped type is stored within the optional itself, alongside a member that indicates the validity state of this optional.
Unlike the std::optional
, taking a estd::optional
of a reference (i.e.
estd::optional<T&>) is allowed and intended as safer alternative to raw
pointers. It implements rebinding semantics. That is, after assigning to an
optional reference, it references the right-hand-side value of the assignment.
Unlike dereferencing a nullptr, trying to access an empty optional will assert
immediately and not cause undefined behavior.
For integral types that have a value that will never be used, estd::limited
may be used instead which exposes an interface similar to optional. The special
forbidden value is then used to indicate the invalid state. This eliminates the
memory overhead of the dedicated validity state member that optional has.
Usage
The usage guidelines apply for ‘optional:
Usage guidance |
optional instance should be checked if it is empty or not before accessing the elements. Accessing the empty optional instance will result in an assertion. |
Example
estd::optional
is a wrapper that adds an additional possible value to the
wrapped type. optional intended as safer alternative to raw pointers.
The following example shows creation of optional instance:
// Creating empty optional instance of the class optional final.
::estd::optional<int32_t> a;
// Returns false, since 'a' is empty.
EXPECT_FALSE(a.has_value());
// Creating an optional instance with value being passed to it.
::estd::optional<int32_t> b = 11;
::estd::optional<int32_t> c(5);
// Creating and assigning an optional instance from another optional instance.
::estd::optional<int32_t> d(b);
EXPECT_TRUE(b.has_value());
EXPECT_TRUE(c.has_value());
EXPECT_TRUE(d.has_value());
// Creating constant optional instance of the class optional final.
::estd::optional<int32_t> const e(10);
// Creating empty optional instance of the class optional<T&>
::estd::optional<int32_t&> ir;
// Returns false, since 'ir' is empty.
EXPECT_FALSE(ir.has_value());
// Creating constant empty optional instance of the class optional<T&>
::estd::optional<int32_t&> const irr;
// Creating an optional instance of the class optional<T&> with reference being passed to it.
int32_t i = 0;
::estd::optional<int32_t&> ir2(i);
ASSERT_TRUE(ir2.has_value());
The following example shows dereferencing the value using operator->() and operator*():
// Defining a class 'SomeClass' with parameterized constructor
class SomeClass
{
public:
int i;
SomeClass(int i) : i(i) {}
};
::estd::optional<int32_t> a(5);
ASSERT_TRUE(a.has_value());
// dereferencing the value using operator*().
EXPECT_EQ(5, *a);
// Changing the value of 'a'.
a = 10;
EXPECT_EQ(10, *a);
::estd::optional<SomeClass> optionalObject = SomeClass(42);
// dereferencing the value using operator->().
EXPECT_EQ(optionalObject->i, 42);
int32_t b = 0;
::estd::optional<int32_t&> ir(b);
ASSERT_TRUE(ir.has_value());
// dereferencing the value using operator*()
EXPECT_EQ(b, *ir);
// dereferencing the value using operator->().
EXPECT_EQ(&b, ir.operator->());
The following example shows usage of ‘value_or()’ function:
::estd::optional<int32_t> i;
// i.value_or(5) returns 5, since 'i' is empty.
EXPECT_EQ(5, i.value_or(5));
i = 6;
// i.value_or(5) returns 6, since 'i' contains value 6.
EXPECT_EQ(6, i.value_or(5));
The following example shows usage of comparison operators in optional:
::estd::optional<int32_t> i0 = 7;
::estd::optional<int32_t> i1 = 5;
EXPECT_TRUE(i0 == i0);
EXPECT_TRUE(i0 != i1);
i0.reset();
i1.reset();
EXPECT_TRUE(i0 == i1);
EXPECT_FALSE(i0 != i1);