dncurrency/nano/lib/optional_ptr.hpp
2024-10-30 07:40:58 +00:00

91 lines
1.4 KiB
C++

#pragma once
#include <cstddef>
#include <memory>
namespace nano
{
/**
* A space efficient optional which does heap allocation when needed.
* This is an alternative to boost/std::optional when the value type is
* large and often not present.
*
* optional_ptr is similar to using std::unique_ptr as an optional, with the
* main difference being that it's copyable.
*/
template <typename T>
class optional_ptr
{
static_assert (sizeof (T) > alignof (std::max_align_t), "Use [std|boost]::optional");
public:
optional_ptr () = default;
optional_ptr (T const & value) :
ptr (new T{ value })
{
}
optional_ptr (optional_ptr const & other)
{
if (other && other.ptr)
{
ptr = std::make_unique<T> (*other.ptr);
}
}
optional_ptr & operator= (optional_ptr const & other)
{
if (other && other.ptr)
{
ptr = std::make_unique<T> (*other.ptr);
}
return *this;
}
T & operator* ()
{
return *ptr;
}
T const & operator* () const
{
return *ptr;
}
T * const operator->()
{
return ptr.operator->();
}
T const * const operator->() const
{
return ptr.operator->();
}
T const * const get () const
{
debug_assert (is_initialized ());
return ptr.get ();
}
T * const get ()
{
debug_assert (is_initialized ());
return ptr.get ();
}
explicit operator bool () const
{
return static_cast<bool> (ptr);
}
bool is_initialized () const
{
return static_cast<bool> (ptr);
}
private:
std::unique_ptr<T> ptr{ nullptr };
};
}