Skip to content

Commit

Permalink
Add value_ptr
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-PLACET committed Apr 4, 2024
1 parent dbbfd27 commit 9da862d
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ OPTION(BUILD_TESTS "sparrow test suite" OFF)
set(SPARROW_HEADERS
${SPARROW_INCLUDE_DIR}/sparrow/array_data.hpp
${SPARROW_INCLUDE_DIR}/sparrow/buffer.hpp
${SPARROW_INCLUDE_DIR}/sparrow/fixed_size_layout.hpp
${SPARROW_INCLUDE_DIR}/sparrow/data_type.hpp
${SPARROW_INCLUDE_DIR}/sparrow/dynamic_bitset.hpp
${SPARROW_INCLUDE_DIR}/sparrow/fixed_size_layout.hpp
${SPARROW_INCLUDE_DIR}/sparrow/iterator.hpp
${SPARROW_INCLUDE_DIR}/sparrow/memory.hpp
${SPARROW_INCLUDE_DIR}/sparrow/mp_utils.hpp
${SPARROW_INCLUDE_DIR}/sparrow/sparrow_version.hpp
${SPARROW_INCLUDE_DIR}/sparrow/variable_size_binary_layout.hpp
Expand Down
83 changes: 83 additions & 0 deletions include/sparrow/memory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <stdexcept>
#include <memory>

namespace sparrow {

template <class T>
class value_ptr {
public:
value_ptr() = default;

explicit value_ptr(T value)
: value_(std::make_unique<T>(std::move(value))) {}

value_ptr(const value_ptr& other)
: value_(other.value_ ? std::make_unique<T>(*other.value_) : std::unique_ptr<T>()){}

value_ptr(value_ptr&& other) noexcept
: value_(std::move(other.value_)) {
other.reset();
}

value_ptr& operator=(const value_ptr& other) {
if (other.has_value()) {
value_ = std::make_unique<T>(*other.value_);
}else {
value_.reset();
}
return *this;
}

value_ptr& operator=(value_ptr&& other) noexcept {
if (this != &other) {
value_ = std::move(other.value_);
other.reset();
}
return *this;
}

T& operator*() {
if (!value_) {
throw std::runtime_error("No value stored in value_ptr");
}
return *value_;
}

const T& operator*() const {
if (!value_) {
throw std::runtime_error("No value stored in value_ptr");
}
return *value_;
}

T* operator->() {
if (!value_) {
throw std::runtime_error("No value stored in value_ptr");
}
return &*value_;
}

const T* operator->() const {
if (!value_) {
throw std::runtime_error("No value stored in value_ptr");
}
return &*value_;
}

explicit operator bool() const noexcept {
return has_value();
}

bool has_value() const noexcept {
return bool(value_);
}

void reset() noexcept {
value_.reset();
}

private:
std::unique_ptr<T> value_;
};

}
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(SPARROW_TESTS_SOURCES
test_layout.cpp
test_variable_size_binary_layout.cpp
test_dictionary_encoded_layout.cpp
test_memory.cpp
)
set(test_target "test_sparrow_lib")
add_executable(${test_target} ${SPARROW_TESTS_SOURCES})
Expand Down
109 changes: 109 additions & 0 deletions test/test_memory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <functional>

#include "sparrow/memory.hpp"

#include "doctest/doctest.h"

using namespace sparrow;

TEST_SUITE("value_ptr")
{
TEST_CASE("constructor")
{
value_ptr<int> vp;
CHECK(!vp);

value_ptr vp1(42);
REQUIRE(vp1);
CHECK(*vp1 == 42);
}

TEST_CASE("copy constructor")
{
value_ptr vp1(42);
value_ptr vp2(vp1);
REQUIRE(vp1);
REQUIRE(vp2);
CHECK(*vp1 == 42);
CHECK(*vp2 == 42);
}

TEST_CASE("copy")
{
value_ptr vp1(42);
value_ptr vp2 = vp1;
REQUIRE(vp1);
REQUIRE(vp2);
CHECK(*vp1 == 42);
CHECK(*vp2 == 42);
}

TEST_CASE("move constructor")
{
value_ptr vp1(42);
value_ptr vp2(std::move(vp1));
CHECK(!vp1);
REQUIRE(vp2);
CHECK(*vp2 == 42);
}

TEST_CASE("move assignment")
{
value_ptr vp1(42);
value_ptr<int> vp2;
vp2 = std::move(vp1);
CHECK(!vp1);
REQUIRE(vp2);
CHECK(*vp2 == 42);

value_ptr<int> vp3;
{
value_ptr vp4(43);
vp3 = std::move(vp4);
}
REQUIRE(vp3);
CHECK(*vp3 == 43);
}

TEST_CASE("operator*")
{
value_ptr vp(42);
CHECK(*vp == 42);

*vp = 43;
CHECK(*vp == 43);
}

TEST_CASE("operator->")
{
value_ptr vp(std::vector<int>{42});
CHECK(vp.operator->() == &*vp);
CHECK(vp->size() == 1);
}

TEST_CASE("operator bool")
{
value_ptr<int> vp;
CHECK(!vp);

value_ptr vp1(42);
CHECK(vp1);
}

TEST_CASE("has_value")
{
value_ptr<int> vp;
CHECK(!vp.has_value());

value_ptr vp1(42);
CHECK(vp1.has_value());
}

TEST_CASE("reset")
{
value_ptr vp(42);
REQUIRE(vp);
vp.reset();
CHECK(!vp);
}
}

0 comments on commit 9da862d

Please sign in to comment.