diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-09-03 16:13:54 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-09-03 16:23:38 +0300 |
commit | 4a23bc2f0f1ebf6cfcf1bae08e95f55f759c9b22 (patch) | |
tree | e065cb5399b54fe2bbb3357ec63d38e56a81470b | |
parent | 3da5a68ec3c329240e89bd0ed8c1c39e4359a693 (diff) | |
download | ydb-4a23bc2f0f1ebf6cfcf1bae08e95f55f759c9b22.tar.gz |
Intermediate changes
-rw-r--r-- | library/cpp/yt/misc/non_null_ptr-inl.h | 49 | ||||
-rw-r--r-- | library/cpp/yt/misc/non_null_ptr.h | 76 | ||||
-rw-r--r-- | library/cpp/yt/misc/unittests/non_null_ptr_ut.cpp | 102 | ||||
-rw-r--r-- | library/cpp/yt/misc/unittests/ya.make | 1 |
4 files changed, 228 insertions, 0 deletions
diff --git a/library/cpp/yt/misc/non_null_ptr-inl.h b/library/cpp/yt/misc/non_null_ptr-inl.h new file mode 100644 index 0000000000..a14b1e9302 --- /dev/null +++ b/library/cpp/yt/misc/non_null_ptr-inl.h @@ -0,0 +1,49 @@ +#pragma once +#ifndef NON_NULL_PTR_H_ +#error "Direct inclusion of this file is not allowed, include helpers.h" +// For the sake of sane code completion. +#include "non_null_ptr.h" +#endif + +#include <library/cpp/yt/assert/assert.h> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +TNonNullPtrBase<T>::TNonNullPtrBase(T* ptr) noexcept + : Ptr_(ptr) +{ + YT_VERIFY(ptr); +} + +template <class T> +T* TNonNullPtrBase<T>::operator->() const noexcept +{ + return Ptr_; +} + +template <class T> +T& TNonNullPtrBase<T>::operator*() const noexcept +{ + return *Ptr_; +} + +template <class T> +TNonNullPtrBase<T>::TNonNullPtrBase() noexcept + : Ptr_(nullptr) +{ } + +template <class T> +TNonNullPtr<T> GetPtr(T& ref) noexcept +{ + TNonNullPtr<T> ptr; + ptr.Ptr_ = &ref; + + return ptr; +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/library/cpp/yt/misc/non_null_ptr.h b/library/cpp/yt/misc/non_null_ptr.h new file mode 100644 index 0000000000..0005e4edb6 --- /dev/null +++ b/library/cpp/yt/misc/non_null_ptr.h @@ -0,0 +1,76 @@ +#pragma once + +#include "concepts.h" + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +// We have one really strange rule in our codestyle - mutable arguments are passed by pointer. +// But if you are not a fan of making your life indefinite, +// you can use this helper, that will validate that pointer you pass is not null. +template <class T> +class TNonNullPtr; + +template <class T> +class TNonNullPtrBase +{ +public: + TNonNullPtrBase(T* ptr) noexcept; + TNonNullPtrBase(const TNonNullPtrBase& other) = default; + + TNonNullPtrBase(std::nullptr_t) = delete; + TNonNullPtrBase operator=(const TNonNullPtrBase&) = delete; + + T* operator->() const noexcept; + T& operator*() const noexcept; + +protected: + T* Ptr_; + + TNonNullPtrBase() noexcept; +}; + +template <class T> +TNonNullPtr<T> GetPtr(T& ref) noexcept; + +template <class T> +class TNonNullPtr + : public TNonNullPtrBase<T> +{ + using TConstPtr = TNonNullPtr<const T>; + friend TConstPtr; + + using TNonNullPtrBase<T>::TNonNullPtrBase; + + friend TNonNullPtr<T> GetPtr<T>(T& ref) noexcept; +}; + +// NB(pogorelov): Method definitions placed in .h file (instead of -inl.h) because of clang16 bug. +// TODO(pogorelov): Move method definitions to helpers-inl.h when new clang will be used. +template <CConst T> +class TNonNullPtr<T> + : public TNonNullPtrBase<T> +{ + using TMutPtr = TNonNullPtr<std::remove_const_t<T>>; + + using TNonNullPtrBase<T>::TNonNullPtrBase; + + friend TNonNullPtr<T> GetPtr<T>(T& ref) noexcept; + +public: + TNonNullPtr(TMutPtr mutPtr) noexcept + : TNonNullPtrBase<T>() + { + TNonNullPtrBase<T>::Ptr_ = mutPtr.Ptr_; + } +}; + + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT + +#define NON_NULL_PTR_H_ +#include "non_null_ptr-inl.h" +#undef NON_NULL_PTR_H_ diff --git a/library/cpp/yt/misc/unittests/non_null_ptr_ut.cpp b/library/cpp/yt/misc/unittests/non_null_ptr_ut.cpp new file mode 100644 index 0000000000..a6903edc40 --- /dev/null +++ b/library/cpp/yt/misc/unittests/non_null_ptr_ut.cpp @@ -0,0 +1,102 @@ +#include <library/cpp/testing/gtest/gtest.h> + +#include <library/cpp/yt/misc/non_null_ptr.h> + +namespace NYT { +namespace { + +//////////////////////////////////////////////////////////////////////////////// + +enum EFuncResult { + Base, + ConstBase, + Derived, + ConstDerived, +}; + +enum EBinaryFuncResult { + Ok, + NotOk, +}; + +struct TBase +{ }; + +struct TDerived + : public TBase +{ }; + +EFuncResult Foo(TNonNullPtr<TBase> /*base*/) +{ + return EFuncResult::Base; +} + +EFuncResult Foo(TNonNullPtr<const TBase> /*base*/) +{ + return EFuncResult::ConstBase; +} + +EFuncResult Foo(TNonNullPtr<TDerived> /*derived*/) +{ + return EFuncResult::Derived; +} + +EFuncResult Foo(TNonNullPtr<const TDerived> /*derived*/) +{ + return EFuncResult::ConstDerived; +} + +[[maybe_unused]] EBinaryFuncResult Foo(int* /*derived*/) +{ + return EBinaryFuncResult::NotOk; +} + +EBinaryFuncResult Foo(TNonNullPtr<int> /*derived*/) +{ + return EBinaryFuncResult::Ok; +} + +EBinaryFuncResult Bar(TNonNullPtr<const int> /*arg*/) +{ + return EBinaryFuncResult::Ok; +} + +EBinaryFuncResult Baz(TNonNullPtr<int> /*arg*/) +{ + return EBinaryFuncResult::Ok; +} + +TEST(TNonNullPtrTest, Simple) +{ + TDerived derived{}; + const auto& constDerived = derived; + EXPECT_EQ(EFuncResult::Derived, Foo(GetPtr(derived))); + EXPECT_EQ(EFuncResult::ConstDerived, Foo(GetPtr(constDerived))); + + TBase base{}; + const auto& constBase = base; + EXPECT_EQ(EFuncResult::Base, Foo(GetPtr(base))); + EXPECT_EQ(EFuncResult::ConstBase, Foo(GetPtr(constBase))); + + int i{}; + EXPECT_EQ(EBinaryFuncResult::Ok, Foo(GetPtr(i))); +} + +TEST(TNonNullPtrTest, CastToConst) +{ + int i{}; + + EXPECT_EQ(EBinaryFuncResult::Ok, Bar(GetPtr(i))); +} + +TEST(TNonNullPtrTest, ConstructionFromRawPointer) +{ + int i{}; + + EXPECT_EQ(EBinaryFuncResult::Ok, Baz(&i)); +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace +} // namespace NYT diff --git a/library/cpp/yt/misc/unittests/ya.make b/library/cpp/yt/misc/unittests/ya.make index 611edd7217..5a071c887c 100644 --- a/library/cpp/yt/misc/unittests/ya.make +++ b/library/cpp/yt/misc/unittests/ya.make @@ -5,6 +5,7 @@ INCLUDE(${ARCADIA_ROOT}/library/cpp/yt/ya_cpp.make.inc) SRCS( enum_ut.cpp guid_ut.cpp + non_null_ptr_ut.cpp preprocessor_ut.cpp strong_typedef_ut.cpp ) |