#include #include namespace xgboost { namespace { class NotCopyConstructible { public: float data; explicit NotCopyConstructible(float d) : data{d} {} NotCopyConstructible(NotCopyConstructible const &that) = delete; NotCopyConstructible &operator=(NotCopyConstructible const &that) = delete; NotCopyConstructible(NotCopyConstructible&& that) = default; }; static_assert( !std::is_trivially_copy_constructible::value, ""); static_assert( !std::is_trivially_copy_assignable::value, ""); class ForIntrusivePtrTest { public: mutable class IntrusivePtrCell ref; float data { 0 }; friend IntrusivePtrCell & IntrusivePtrRefCount(ForIntrusivePtrTest const *t) noexcept { // NOLINT return t->ref; } ForIntrusivePtrTest() = default; ForIntrusivePtrTest(float a, int32_t b) : data{a + static_cast(b)} {} explicit ForIntrusivePtrTest(NotCopyConstructible a) : data{a.data} {} }; } // anonymous namespace TEST(IntrusivePtr, Basic) { IntrusivePtr ptr {new ForIntrusivePtrTest}; auto p = ptr.get(); // Copy ctor IntrusivePtr ptr_1 { ptr }; ASSERT_EQ(ptr_1.get(), p); ASSERT_EQ((*ptr_1).data, ptr_1->data); ASSERT_EQ(ptr.use_count(), 2); // hash ASSERT_EQ(std::hash>{}(ptr_1), std::hash{}(ptr_1.get())); // Raw ptr comparison ASSERT_EQ(ptr, p); ASSERT_EQ(ptr_1, ptr); ForIntrusivePtrTest* raw_ptr {nullptr}; ASSERT_NE(ptr_1, raw_ptr); ASSERT_NE(raw_ptr, ptr_1); // Reset with raw ptr. auto p_1 = new ForIntrusivePtrTest; ptr.reset(p_1); ASSERT_EQ(ptr_1.use_count(), 1); ASSERT_EQ(ptr.use_count(), 1); ASSERT_TRUE(ptr); ASSERT_TRUE(ptr_1); // Swap std::swap(ptr, ptr_1); ASSERT_NE(ptr, p_1); ASSERT_EQ(ptr_1, p_1); // Reset ptr.reset(); ASSERT_FALSE(ptr); ASSERT_EQ(ptr.use_count(), 0); // Comparison operators ASSERT_EQ(ptr < ptr_1, ptr.get() < ptr_1.get()); ASSERT_EQ(ptr > ptr_1, ptr.get() > ptr_1.get()); ASSERT_LE(ptr, ptr); ASSERT_GE(ptr, ptr); // Copy assign IntrusivePtr ptr_2; ptr_2 = ptr_1; ASSERT_EQ(ptr_2, ptr_1); ASSERT_EQ(ptr_2.use_count(), 2); // Move assign IntrusivePtr ptr_3; ptr_3 = std::move(ptr_2); ASSERT_EQ(ptr_2.use_count(), 0); // NOLINT ASSERT_EQ(ptr_3.use_count(), 2); // Move ctor IntrusivePtr ptr_4 { std::move(ptr_3) }; ASSERT_EQ(ptr_3.use_count(), 0); // NOLINT ASSERT_EQ(ptr_4.use_count(), 2); // Comparison ASSERT_EQ(ptr_1 > ptr_2, ptr_1.get() > ptr_2.get()); ASSERT_EQ(ptr_1, ptr_1); ASSERT_EQ(ptr_1 < ptr_2, ptr_1.get() < ptr_2.get()); } } // namespace xgboost