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