C++ Optional Reference
Design

References are different from pointers in two ways:


they are designed to be aliases to the objects they refer to, so syntactically they are treated with special care;
they cannot be rebound.


You cannot always emulate the first bullet with an optional &mdash; for example, there's no general way to make opt.f() call opt.value().f().  You still have to resort to some other syntax like opt-&gt;value().  Therefore, my advice is to simply treat opt_ref&lt;T&gt; like an immutable nullable pointer that does not own the referred-to object &mdash; don't follow std::reference_wrapper.

Code Review


using type = typename std::reference_wrapper&lt;T&gt;::type;



typename std::reference_wrapper&lt;T&gt;::type is just T.  Also, the standard terminology is value_type.


T&amp; get() { return data.value().get(); }
const T&amp; get() const { return data.value().get(); }
bool has_value() const { return data.has_value(); }
T&amp; value_or(T&amp;&amp; other) const { return data.value_or(other); }



has_value is noexcept.  Why does value_or take an rvalue reference?  To introduce dangling references as in opt.value_or(1)?  Take an lvalue reference instead.


bool operator == (const T&amp; t) { return data.value() == t; }
bool operator == (const std::nullopt_t&amp;) {return !data.has_value(); }



I'm not sure this is the right approach.  The first == compares values (and throws an exception if there is no value), whereas the second == compares the references themselves.  You can imitate the behavior of std::optional:

bool operator==(const opt_ref&lt;T&gt;&amp; a, const opt_ref&lt;T&gt;&amp; b)
{
    if (a.has_value() != b.has_value()) {
        return false;
    } else if (!a.has_value()) { // and !b.has_value()
        return true;
    } else {
        return a.get() == b.get();
    }
}



operator T&amp;() { return data.value().get(); }
operator const T&amp;() const { return data.value().get(); }
operator std::reference_wrapper&lt;T&gt;() { return data.value(); }
operator const std::reference_wrapper&lt;T&gt;() const { return data.value(); }



As I said before: are you sure you want this (especially the implicit conversions to reference_wrapper)?

Other functionalities

Consider:


operator* and operator-&gt;;
explicit operator bool;
has_value;
...