mirror of https://github.com/facebook/rocksdb.git
Create an UnownedPtr type (#12447)
Summary: ... that is more hygienic as an "optional reference" than a raw pointer, and likely more efficient than std::optional<std::reference_wrapper<T>>. Pull Request resolved: https://github.com/facebook/rocksdb/pull/12447 Test Plan: unit test included (with manual verification that "must not compile" sections currently do not) Reviewed By: jowlyzhang Differential Revision: D54957917 Pulled By: pdillinger fbshipit-source-id: bbd89218df803617b1a170ebddc9e56c9b52bf93
This commit is contained in:
parent
096fb9b67d
commit
c3c0cfc3a8
|
@ -63,4 +63,26 @@ inline const std::initializer_list<T>& List(
|
|||
return list;
|
||||
}
|
||||
|
||||
// UnownedPtr<T> is useful as an efficient "optional reference" that can't
|
||||
// be accidentally converted to std::shared_ptr<T> nor std::unique_ptr<T>.
|
||||
template <typename T>
|
||||
class UnownedPtr {
|
||||
public:
|
||||
UnownedPtr() = default;
|
||||
UnownedPtr(std::nullptr_t) {}
|
||||
UnownedPtr(T* ptr) : ptr_(ptr) {}
|
||||
UnownedPtr(const UnownedPtr&) = default;
|
||||
UnownedPtr(UnownedPtr&&) = default;
|
||||
UnownedPtr& operator=(const UnownedPtr&) = default;
|
||||
UnownedPtr& operator=(UnownedPtr&&) = default;
|
||||
|
||||
T* get() const { return ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
T& operator*() const { return *ptr_; }
|
||||
operator bool() const { return ptr_ != nullptr; }
|
||||
|
||||
private:
|
||||
T* ptr_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "rocksdb/types.h"
|
||||
#include "test_util/testharness.h"
|
||||
#include "test_util/testutil.h"
|
||||
#include "util/cast_util.h"
|
||||
|
||||
namespace ROCKSDB_NAMESPACE {
|
||||
|
||||
|
@ -273,6 +274,71 @@ TEST(StatusTest, Update) {
|
|||
ASSERT_TRUE(s.IsNotFound());
|
||||
}
|
||||
|
||||
// ***************************************************************** //
|
||||
// Unit test for UnownedPtr
|
||||
TEST(UnownedPtrTest, Tests) {
|
||||
{
|
||||
int x = 0;
|
||||
UnownedPtr<int> p(&x);
|
||||
ASSERT_EQ(p.get(), &x);
|
||||
ASSERT_EQ(*p, 0);
|
||||
x = 1;
|
||||
ASSERT_EQ(*p, 1);
|
||||
ASSERT_EQ(p.get(), &x);
|
||||
ASSERT_EQ(*p, 1);
|
||||
*p = 2;
|
||||
ASSERT_EQ(x, 2);
|
||||
ASSERT_EQ(*p, 2);
|
||||
ASSERT_EQ(p.get(), &x);
|
||||
ASSERT_EQ(*p, 2);
|
||||
}
|
||||
{
|
||||
std::unique_ptr<std::pair<int, int>> u =
|
||||
std::make_unique<std::pair<int, int>>();
|
||||
*u = {1, 2};
|
||||
UnownedPtr<std::pair<int, int>> p;
|
||||
ASSERT_FALSE(p);
|
||||
p = u.get();
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->first, 1);
|
||||
// These must not compile:
|
||||
/*
|
||||
u = p;
|
||||
u = std::move(p);
|
||||
std::unique_ptr<std::pair<int, int>> v{p};
|
||||
std::unique_ptr<std::pair<int, int>> v{std::move(p)};
|
||||
*/
|
||||
// END must not compile
|
||||
|
||||
UnownedPtr<std::pair<int, int>> q;
|
||||
q = std::move(p);
|
||||
ASSERT_EQ(q->first, 1);
|
||||
// Not committing to any moved-from semantics (on p here)
|
||||
}
|
||||
{
|
||||
std::shared_ptr<std::pair<int, int>> s =
|
||||
std::make_shared<std::pair<int, int>>();
|
||||
*s = {1, 2};
|
||||
UnownedPtr<std::pair<int, int>> p;
|
||||
ASSERT_FALSE(p);
|
||||
p = s.get();
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->first, 1);
|
||||
// These must not compile:
|
||||
/*
|
||||
s = p;
|
||||
s = std::move(p);
|
||||
std::unique_ptr<std::pair<int, int>> t{p};
|
||||
std::unique_ptr<std::pair<int, int>> t{std::move(p)};
|
||||
*/
|
||||
// END must not compile
|
||||
UnownedPtr<std::pair<int, int>> q;
|
||||
q = std::move(p);
|
||||
ASSERT_EQ(q->first, 1);
|
||||
// Not committing to any moved-from semantics (on p here)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
Loading…
Reference in New Issue