Here is a good article on an optional reference type in C++. They discuss std::optional<T&>, but as that doesn't compile I have made my own.
One purpose of this type is to remove raw pointers from function signatures (where references alone cannot be used), as a raw pointer does not convey any indication of what it will be used for (become owned, deleted, iterated, dereferenced, etc).
#include <functional>
#include <optional>
template<typename T>
/** @brief An optional refference **/
class opt_ref {
using std_opt_ref = std::optional<std::reference_wrapper<T>>;
std_opt_ref data = std::nullopt;
public:
using type = typename std::reference_wrapper<T>::type;
/** public member functions **/
T& get() { return data.value().get(); }
const T& get() const { return data.value().get(); }
bool has_value() const { return data.has_value(); }
T& value_or(T&& other) const { return data.value_or(other); }
/** constructors **/
opt_ref() {}
opt_ref(T& source) : data(source) {}
opt_ref& operator = (T&& other) { data.value().get() = other; return *this; }
/** comparisons **/
bool operator == (const T& t) { return data.value() == t; }
bool operator == (const std::nullopt_t&) {return !data.has_value(); }
/** implicit conversion **/
operator T&() { return data.value().get(); }
operator const T&() const { return data.value().get(); }
operator std::reference_wrapper<T>() { return data.value(); }
operator const std::reference_wrapper<T>() const { return data.value(); }
};