Skip to content

Commit

Permalink
Allow creation of box and ref through std::unique_ptr and std::shared…
Browse files Browse the repository at this point in the history
…_ptr respectively
  • Loading branch information
liuzicheng1987 committed Mar 31, 2024
1 parent 4fa84ff commit 86f7312
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 2 deletions.
10 changes: 10 additions & 0 deletions docs/rfl_ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,16 @@ This will result in the following JSON string:
{"leafOrNode":{"type":"Node","criticalValue":10.0,"lesser":{"leafOrNode":{"type":"Leaf","value":3.0}},"greater":{"leafOrNode":{"type":"Leaf","value":5.0}}}}
```
You can also initialize `rfl::Box<T>` from a `std::unique_ptr<T>`:
```cpp
auto ptr = std::make_unique<std::string>("Hello World!");
const rfl::Result<rfl::Box<std::string>> box = rfl::make_box<std::string>(std::move(ptr));
```
Note that `box` is wrapped in a `Result`. That is, because we cannot guarantee at compile time
that `ptr` is not `nullptr`, therefore we need to account for that.
If you want to use reference-counted pointers, instead of unique pointers, you can use `rfl::Ref`.
`rfl::Ref` is the same concept as `rfl::Box`, but using `std::shared_ptr` under-the-hood.
Expand Down
13 changes: 12 additions & 1 deletion include/rfl/Box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <memory>
#include <stdexcept>

#include "Result.hpp"

namespace rfl {

/// The Box class behaves very similarly to the unique_ptr, but unlike the
Expand All @@ -20,6 +22,15 @@ class Box {
return Box<T>(std::make_unique<T>(std::forward<Args>(_args)...));
}

/// You can generate them from unique_ptrs as well, in which case it will
/// return an Error, if the unique_ptr is not set.
static Result<Box<T>> make(std::unique_ptr<T>&& _ptr) {
if (!_ptr) {
return Error("std::unique_ptr was a nullptr.");
}
return Box<T>(std::move(_ptr));
}

Box() : ptr_(std::make_unique<T>()) {}

Box(const Box<T>& _other) = delete;
Expand Down Expand Up @@ -77,7 +88,7 @@ class Box {

/// Generates a new Ref<T>.
template <class T, class... Args>
Box<T> make_box(Args&&... _args) {
auto make_box(Args&&... _args) {
return Box<T>::make(std::forward<Args>(_args)...);
}

Expand Down
22 changes: 21 additions & 1 deletion include/rfl/Ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <memory>
#include <stdexcept>

#include "Result.hpp"

namespace rfl {

/// The Ref class behaves very similarly to the shared_ptr, but unlike the
Expand All @@ -20,6 +22,24 @@ class Ref {
return Ref<T>(std::make_shared<T>(std::forward<Args>(_args)...));
}

/// You can generate them from shared_ptrs as well, in which case it will
/// return an Error, if the shared_ptr is not set.
static Result<Ref<T>> make(std::shared_ptr<T>&& _ptr) {
if (!_ptr) {
return Error("std::shared_ptr was a nullptr.");
}
return Ref<T>(std::move(_ptr));
}

/// You can generate them from shared_ptrs as well, in which case it will
/// return an Error, if the shared_ptr is not set.
static Result<Ref<T>> make(const std::shared_ptr<T>& _ptr) {
if (!_ptr) {
return Error("std::shared_ptr was a nullptr.");
}
return Ref<T>(_ptr);
}

Ref() : ptr_(std::make_shared<T>()) {}

Ref(const Ref<T>& _other) = default;
Expand Down Expand Up @@ -87,7 +107,7 @@ class Ref {

/// Generates a new Ref<T>.
template <class T, class... Args>
Ref<T> make_ref(Args&&... _args) {
auto make_ref(Args&&... _args) {
return Ref<T>::make(std::forward<Args>(_args)...);
}

Expand Down
27 changes: 27 additions & 0 deletions tests/json/test_box2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <cassert>
#include <iostream>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <source_location>
#include <string>
#include <vector>

#include "test_box.hpp"

namespace test_box2 {

void test() {
std::cout << std::source_location::current().function_name() << std::endl;

auto ptr = std::make_unique<std::string>("Hello World!");
const rfl::Result<rfl::Box<std::string>> box =
rfl::make_box<std::string>(std::move(ptr));

if (box) {
std::cout << "OK" << std::endl << std::endl;
} else {
std::cout << "Expected the result to be successful." << std::endl
<< std::endl;
}
}
} // namespace test_box2
4 changes: 4 additions & 0 deletions tests/json/test_box2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace test_box2 {
void test();
}

2 changes: 2 additions & 0 deletions tests/json/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "test_as2.hpp"
#include "test_as_flatten.hpp"
#include "test_box.hpp"
#include "test_box2.hpp"
#include "test_c_array_class1.hpp"
#include "test_c_array_class2.hpp"
#include "test_c_array_class3.hpp"
Expand Down Expand Up @@ -98,6 +99,7 @@ int main() {
test_field_variant::test();
test_ref::test();
test_box::test();
test_box2::test();
test_array::test();
test_timestamp::test();
test_flatten::test();
Expand Down

0 comments on commit 86f7312

Please sign in to comment.