#pragma once #include 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 TNonNullPtr; template 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 TNonNullPtr GetPtr(T& ref) noexcept; template class TNonNullPtr : public TNonNullPtrBase { using TConstPtr = TNonNullPtr; friend TConstPtr; using TNonNullPtrBase::TNonNullPtrBase; friend TNonNullPtr GetPtr(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 class TNonNullPtr : public TNonNullPtrBase { using TMutablePtr = TNonNullPtr>; using TNonNullPtrBase::TNonNullPtrBase; friend TNonNullPtr GetPtr(T& ref) noexcept; public: TNonNullPtr(TMutablePtr mutPtr) noexcept : TNonNullPtrBase() { TNonNullPtrBase::Ptr_ = mutPtr.Ptr_; } }; //////////////////////////////////////////////////////////////////////////////// } // namespace NYT #define NON_NULL_PTR_H_ #include "non_null_ptr-inl.h" #undef NON_NULL_PTR_H_