diff options
| author | ilnurkh <[email protected]> | 2025-04-25 13:55:53 +0300 |
|---|---|---|
| committer | ilnurkh <[email protected]> | 2025-04-25 14:44:41 +0300 |
| commit | c0533d88038a1fc7c4753c986e6c47bb4cbd21b7 (patch) | |
| tree | a0f8a9a9258adc10804fe96aaca4f7c5a578d593 | |
| parent | cecedbe2b29df37e09409fc2d15fb8211269d8b1 (diff) | |
GetRef in TPointerCommon
commit_hash:4149625a81c51af40642fe498a887608cc57305f
| -rw-r--r-- | util/generic/ptr.cpp | 5 | ||||
| -rw-r--r-- | util/generic/ptr.h | 16 | ||||
| -rw-r--r-- | util/generic/ptr_ut.cpp | 29 |
3 files changed, 50 insertions, 0 deletions
diff --git a/util/generic/ptr.cpp b/util/generic/ptr.cpp index b29baebc175..963dcd5160c 100644 --- a/util/generic/ptr.cpp +++ b/util/generic/ptr.cpp @@ -1,4 +1,5 @@ #include "ptr.h" +#include "yexception.h" #include <util/system/defaults.h> #include <util/memory/alloc.h> @@ -15,3 +16,7 @@ void TDelete::Destroy(void* t) noexcept { } TThrRefBase::~TThrRefBase() = default; + +[[noreturn]] void NDetail::NullDerefenceThrowImpl() { + ythrow yexception{} << "nullptr dereference"; +} diff --git a/util/generic/ptr.h b/util/generic/ptr.h index 625418ccdb0..cf28d0bfd2c 100644 --- a/util/generic/ptr.h +++ b/util/generic/ptr.h @@ -100,6 +100,10 @@ private: static void DoDestroy(void* t) noexcept; }; +namespace NDetail { + [[noreturn]] void NullDerefenceThrowImpl(); +} // namespace NDetail + template <class Base, class T> class TPointerCommon { public: @@ -116,6 +120,18 @@ public: return ptr; } + inline typename std::add_lvalue_reference<T>::type GetRef() const { + T* ptr = AsT(); + if (Y_UNLIKELY(!ptr)) { + NDetail::NullDerefenceThrowImpl(); + } + if constexpr (std::is_void<T>::value) { + return; + } else { + return *ptr; + } + } + #ifndef __cpp_impl_three_way_comparison template <class C> inline bool operator==(const C& p) const noexcept { diff --git a/util/generic/ptr_ut.cpp b/util/generic/ptr_ut.cpp index 8f72cee5219..e6a4a7837c0 100644 --- a/util/generic/ptr_ut.cpp +++ b/util/generic/ptr_ut.cpp @@ -36,6 +36,7 @@ class TPointerTest: public TTestBase { UNIT_TEST(TestRefCountedPtrsInHashSet); UNIT_TEST(TestSharedPtrDowncast); UNIT_TEST(TestStdCompatibility); + UNIT_TEST(TestGetRef); UNIT_TEST_SUITE_END(); private: @@ -91,6 +92,7 @@ private: void TestRefCountedPtrsInHashSet(); void TestSharedPtrDowncast(); void TestStdCompatibility(); + void TestGetRef(); }; UNIT_TEST_SUITE_REGISTRATION(TPointerTest); @@ -962,3 +964,30 @@ void TPointerTest::TestStdCompatibility() { UNIT_ASSERT_VALUES_EQUAL(ptr.get(), ptr.Get()); } } + +void TPointerTest::TestGetRef() { + { + TSimpleSharedPtr<int> ptr = MakeSimpleShared<int>(5); + UNIT_ASSERT_TYPES_EQUAL(decltype(ptr.GetRef()), int&); + UNIT_ASSERT_VALUES_EQUAL(ptr.GetRef(), 5); + ptr.GetRef() += 5; + UNIT_ASSERT_VALUES_EQUAL(ptr.GetRef(), 10); + } + { + THolder<const int> ptr = MakeHolder<int>(5); + UNIT_ASSERT_TYPES_EQUAL(decltype(ptr.GetRef()), const int&); + UNIT_ASSERT_VALUES_EQUAL(ptr.GetRef(), 5); + } + { + THolder<const int> ptr; + UNIT_ASSERT_EXCEPTION(ptr.GetRef(), yexception); + } + + { + THolder<void, TNoAction> ptr((void*)10); + UNIT_ASSERT_TYPES_EQUAL(decltype(ptr.GetRef()), void); + ptr.GetRef(); + ptr = {}; + UNIT_ASSERT_EXCEPTION(ptr.GetRef(), yexception); + } +} |
