Utility: nano::optional_ptr (#2605)
* optional_ptr * Implement feedback from Wesley/Guilherme
This commit is contained in:
parent
e10701220f
commit
bac78d0273
3 changed files with 122 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
|||
#include <nano/lib/optional_ptr.hpp>
|
||||
#include <nano/lib/timer.hpp>
|
||||
#include <nano/lib/utility.hpp>
|
||||
#include <nano/lib/worker.hpp>
|
||||
|
@ -7,6 +8,33 @@
|
|||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
TEST (optional_ptr, basic)
|
||||
{
|
||||
struct valtype
|
||||
{
|
||||
int64_t x{ 1 };
|
||||
int64_t y{ 2 };
|
||||
int64_t z{ 3 };
|
||||
};
|
||||
|
||||
nano::optional_ptr<valtype> opt;
|
||||
ASSERT_FALSE (opt);
|
||||
ASSERT_FALSE (opt.is_initialized ());
|
||||
|
||||
{
|
||||
auto val = valtype{};
|
||||
opt = val;
|
||||
ASSERT_LT (sizeof (opt), sizeof (val));
|
||||
std::unique_ptr<valtype> uptr;
|
||||
ASSERT_EQ (sizeof (opt), sizeof (uptr));
|
||||
}
|
||||
ASSERT_TRUE (opt);
|
||||
ASSERT_TRUE (opt.is_initialized ());
|
||||
ASSERT_EQ (opt->x, 1);
|
||||
ASSERT_EQ (opt->y, 2);
|
||||
ASSERT_EQ (opt->z, 3);
|
||||
}
|
||||
|
||||
TEST (thread, worker)
|
||||
{
|
||||
std::atomic<bool> passed_sleep{ false };
|
||||
|
|
|
@ -41,6 +41,7 @@ add_library (nano_lib
|
|||
memory.cpp
|
||||
numbers.hpp
|
||||
numbers.cpp
|
||||
optional_ptr.hpp
|
||||
rep_weights.hpp
|
||||
rep_weights.cpp
|
||||
rocksdbconfig.hpp
|
||||
|
|
93
nano/lib/optional_ptr.hpp
Normal file
93
nano/lib/optional_ptr.hpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/utility.hpp>
|
||||
|
||||
#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 };
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue