diff options
| author | YDBot <[email protected]> | 2026-07-04 05:32:29 +0000 |
|---|---|---|
| committer | YDBot <[email protected]> | 2026-07-04 05:32:29 +0000 |
| commit | 4a7d6319fb151f9bfb88c87181deceb12609ea3b (patch) | |
| tree | 7ffb9c5342cafa0361a191a69b3891ed74033a85 /library/cpp | |
| parent | 6db1f55d653509051c048b736946c0fc7db6e66b (diff) | |
| parent | f7dbea9c1bcabb15221e06721fc9b705ce4111fc (diff) | |
Merge pull request #45508 from ydb-platform/merge-rightlib-260704-0105
Diffstat (limited to 'library/cpp')
| -rw-r--r-- | library/cpp/containers/paged_vector/paged_vector.h | 133 | ||||
| -rw-r--r-- | library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp | 14 | ||||
| -rw-r--r-- | library/cpp/lwtrace/log_shuttle.cpp | 4 | ||||
| -rw-r--r-- | library/cpp/lwtrace/shuttle.h | 4 | ||||
| -rw-r--r-- | library/cpp/lwtrace/trace_ut.cpp | 2 | ||||
| -rw-r--r-- | library/cpp/yt/logging/benchmark/logger_tag.cpp | 32 | ||||
| -rw-r--r-- | library/cpp/yt/logging/benchmark/ya.make | 14 | ||||
| -rw-r--r-- | library/cpp/yt/logging/logger-inl.h | 8 | ||||
| -rw-r--r-- | library/cpp/yt/logging/logger.cpp | 8 | ||||
| -rw-r--r-- | library/cpp/yt/logging/logger.h | 12 | ||||
| -rw-r--r-- | library/cpp/yt/logging/ya.make | 1 | ||||
| -rw-r--r-- | library/cpp/yt/memory/type_erasure.h | 18 | ||||
| -rw-r--r-- | library/cpp/yt/memory/type_erasure_detail.h | 6 | ||||
| -rw-r--r-- | library/cpp/yt/memory/unittests/type_erasure_ut.cpp | 24 |
14 files changed, 190 insertions, 90 deletions
diff --git a/library/cpp/containers/paged_vector/paged_vector.h b/library/cpp/containers/paged_vector/paged_vector.h index 96be0042e0a..a03404c688e 100644 --- a/library/cpp/containers/paged_vector/paged_vector.h +++ b/library/cpp/containers/paged_vector/paged_vector.h @@ -15,36 +15,36 @@ namespace NPagedVector { struct TPagedVectorIterator { private: friend class TPagedVector<TT, PageSize, A>; - typedef TPagedVector<TT, PageSize, A> TVec; - typedef TPagedVectorIterator<T, TT, PageSize, A> TSelf; - size_t Offset; - TVec* Vector; + using TVec = TPagedVector<TT, PageSize, A>; + using TSelf = TPagedVectorIterator<T, TT, PageSize, A>; + size_t Offset_; + TVec* Vector_; template <class T1, class TT1, ui32 PageSize1, class A1> friend struct TPagedVectorIterator; public: TPagedVectorIterator() - : Offset() - , Vector() + : Offset_() + , Vector_() { } TPagedVectorIterator(TVec* vector, size_t offset) - : Offset(offset) - , Vector(vector) + : Offset_(offset) + , Vector_(vector) { } template <class T1, class TT1, ui32 PageSize1, class A1> TPagedVectorIterator(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) - : Offset(it.Offset) - , Vector(it.Vector) + : Offset_(it.Offset_) + , Vector_(it.Vector_) { } T& operator*() const { - return (*Vector)[Offset]; + return (*Vector_)[Offset_]; } T* operator->() const { @@ -53,7 +53,7 @@ namespace NPagedVector { template <class T1, class TT1, ui32 PageSize1, class A1> bool operator==(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const { - return Offset == it.Offset; + return Offset_ == it.Offset_; } template <class T1, class TT1, ui32 PageSize1, class A1> @@ -63,12 +63,12 @@ namespace NPagedVector { template <class T1, class TT1, ui32 PageSize1, class A1> bool operator<(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const { - return Offset < it.Offset; + return Offset_ < it.Offset_; } template <class T1, class TT1, ui32 PageSize1, class A1> bool operator<=(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const { - return Offset <= it.Offset; + return Offset_ <= it.Offset_; } template <class T1, class TT1, ui32 PageSize1, class A1> @@ -83,11 +83,11 @@ namespace NPagedVector { template <class T1, class TT1, ui32 PageSize1, class A1> ptrdiff_t operator-(const TPagedVectorIterator<T1, TT1, PageSize1, A1>& it) const { - return Offset - it.Offset; + return Offset_ - it.Offset_; } TSelf& operator+=(ptrdiff_t off) { - Offset += off; + Offset_ += off; return *this; } @@ -126,44 +126,44 @@ namespace NPagedVector { } size_t GetOffset() const { - return Offset; + return Offset_; } }; - } -} + } // namespace NPrivate +} // namespace NPagedVector namespace std { template <class T, class TT, ui32 PageSize, class A> struct iterator_traits<NPagedVector::NPrivate::TPagedVectorIterator<T, TT, PageSize, A>> { - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* pointer; - typedef T& reference; - typedef random_access_iterator_tag iterator_category; + using difference_type = ptrdiff_t; + using value_type = T; + using pointer = T*; + using reference = T&; + using iterator_category = random_access_iterator_tag; }; -} +} // namespace std namespace NPagedVector { - //2-level radix tree + // 2-level radix tree template <class T, ui32 PageSize, class A> class TPagedVector { static_assert(PageSize, "expect PageSize"); - typedef TVector<T, A> TPage; - typedef TVector<THolder<TPage>, A> TPages; - typedef TPagedVector<T, PageSize, A> TSelf; + using TPage = TVector<T, A>; + using TPages = TVector<THolder<TPage>, A>; + using TSelf = TPagedVector<T, PageSize, A>; TPages Pages_; public: - typedef NPrivate::TPagedVectorIterator<T, T, PageSize, A> iterator; - typedef NPrivate::TPagedVectorIterator<const T, T, PageSize, A> const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef T value_type; - typedef value_type& reference; - typedef const value_type& const_reference; + using iterator = NPrivate::TPagedVectorIterator<T, T, PageSize, A>; + using const_iterator = NPrivate::TPagedVectorIterator<const T, T, PageSize, A>; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using value_type = T; + using reference = value_type&; + using const_reference = const value_type&; TPagedVector() = default; TPagedVector(TPagedVector&& other) noexcept = default; @@ -266,13 +266,14 @@ namespace NPagedVector { } void PrepareAppend() { - if (Pages_.empty() || CurrentPage().size() + 1 > PageSize) + if (Pages_.empty() || CurrentPage().size() >= PageSize) { AllocateNewPage(); + } } public: size_t size() const { - return empty() ? 0 : (NPages() - 1) * PageSize + CurrentPage().size(); + return Pages_.empty() ? 0 : (NPages() - 1) * PageSize + CurrentPage().size(); } bool empty() const { @@ -283,7 +284,7 @@ namespace NPagedVector { return !empty(); } - template<typename... Args> + template <typename... Args> reference emplace_back(Args&&... args) { PrepareAppend(); return CurrentPage().emplace_back(std::forward<Args>(args)...); @@ -295,8 +296,9 @@ namespace NPagedVector { } void pop_back() { - if (CurrentPage().empty()) + if (CurrentPage().empty()) { Pages_.pop_back(); + } CurrentPage().pop_back(); } @@ -327,18 +329,22 @@ namespace NPagedVector { } iterator erase(iterator it) { - size_t pnum = PageNumber(it.Offset); - size_t pidx = InPageIndex(it.Offset); + const size_t pnum = PageNumber(it.Offset_); + const size_t pidx = InPageIndex(it.Offset_); - if (CurrentPage().empty()) + if (CurrentPage().empty()) { Pages_.pop_back(); + } - for (size_t p = NPages() - 1; p > pnum; --p) { - PageAt(p - 1).push_back(PageAt(p).front()); - PageAt(p).erase(PageAt(p).begin()); + auto currentPageIt = Pages_.begin() + pnum; + + (*currentPageIt)->erase((*currentPageIt)->begin() + pidx); + + for (auto nextPageIt = currentPageIt + 1; nextPageIt != Pages_.end(); currentPageIt = nextPageIt, ++nextPageIt) { + (*currentPageIt)->push_back(std::move((**nextPageIt)[0])); + (*nextPageIt)->erase((*nextPageIt)->begin()); } - PageAt(pnum).erase(PageAt(pnum).begin() + pidx); return it; } @@ -353,8 +359,8 @@ namespace NPagedVector { } iterator insert(iterator it, const value_type& v) { - size_t pnum = PageNumber(it.Offset); - size_t pidx = InPageIndex(it.Offset); + size_t pnum = PageNumber(it.Offset_); + size_t pidx = InPageIndex(it.Offset_); PrepareAppend(); @@ -370,8 +376,9 @@ namespace NPagedVector { template <typename TIter> void insert(iterator it, TIter b, TIter e) { // todo : suboptimal! - for (; b != e; ++b, ++it) + for (; b != e; ++b, ++it) { it = insert(it, *b); + } } reference front() { @@ -395,25 +402,30 @@ namespace NPagedVector { } void resize(size_t sz) { - if (sz == size()) + if (sz == size()) { return; + } const size_t npages = NPages(); const size_t newwholepages = sz / PageSize; const size_t pagepart = sz % PageSize; const size_t newpages = newwholepages + bool(pagepart); - if (npages && newwholepages >= npages) + if (npages && newwholepages >= npages) { CurrentPage().resize(PageSize); + } - if (newpages < npages) + if (newpages < npages) { Pages_.resize(newpages); - else - for (size_t i = npages; i < newpages; ++i) + } else { + for (size_t i = npages; i < newpages; ++i) { MakeNewPage(); + } + } - if (pagepart) + if (pagepart) { CurrentPage().resize(pagepart); + } Y_ABORT_UNLESS(sz == size(), "%" PRIu64 " %" PRIu64, (ui64)sz, (ui64)size()); } @@ -444,10 +456,9 @@ namespace NPagedVector { }; namespace NPrivate { - typedef std::is_same<std::random_access_iterator_tag, std::iterator_traits< - TPagedVector<ui32>::iterator>::iterator_category> - TIteratorCheck; + using TIteratorCheck = std::is_same<std::random_access_iterator_tag, std::iterator_traits< + TPagedVector<ui32>::iterator>::iterator_category>; static_assert(TIteratorCheck::value, "expect TIteratorCheck::Result"); - } + } // namespace NPrivate -} +} // namespace NPagedVector diff --git a/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp b/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp index 54e4b71fa70..7f93676a3c2 100644 --- a/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp +++ b/library/cpp/containers/paged_vector/ut/paged_vector_ut.cpp @@ -126,8 +126,9 @@ private: TPagedVector<char, 1> v2; v2.resize(v1.size()); - for (size_t i = 0; i < v1.size(); ++i) + for (size_t i = 0; i < v1.size(); ++i) { v2[i] = v1[i]; + } v2[1] = 'o'; // Replace second character. @@ -336,14 +337,14 @@ private: UNIT_ASSERT(vint.rbegin() == vint.rbegin()); // Not Standard: - //UNIT_ASSERT(vint.rbegin() == crvint.rbegin()); - //UNIT_ASSERT(crvint.rbegin() == vint.rbegin()); + // UNIT_ASSERT(vint.rbegin() == crvint.rbegin()); + // UNIT_ASSERT(crvint.rbegin() == vint.rbegin()); UNIT_ASSERT(crvint.rbegin() == crvint.rbegin()); UNIT_ASSERT(vint.rbegin() != vint.rend()); // Not Standard: - //UNIT_ASSERT(vint.rbegin() != crvint.rend()); - //UNIT_ASSERT(crvint.rbegin() != vint.rend()); + // UNIT_ASSERT(vint.rbegin() != crvint.rend()); + // UNIT_ASSERT(crvint.rbegin() != vint.rend()); UNIT_ASSERT(crvint.rbegin() != crvint.rend()); } @@ -505,8 +506,9 @@ private: V* pv2 = new V; pv2->resize(10); - for (int i = 0; i < 10; ++i) + for (int i = 0; i < 10; ++i) { pv2->at(i) = 2; + } pv1->swap(*pv2); diff --git a/library/cpp/lwtrace/log_shuttle.cpp b/library/cpp/lwtrace/log_shuttle.cpp index 695aa90b316..a6563efb5b9 100644 --- a/library/cpp/lwtrace/log_shuttle.cpp +++ b/library/cpp/lwtrace/log_shuttle.cpp @@ -22,7 +22,9 @@ namespace NLWTrace { template <class TDepot> bool TLogShuttle<TDepot>::DoFork(TShuttlePtr& child) { - if (child = Executor->RentShuttle()) { + if (auto shuttle = Executor->RentShuttle()) { + shuttle->SetNext(child); + child = shuttle; child->SetParentSpanId(GetSpanId()); Executor->Cast(child)->SetIgnore(true); TParams params; diff --git a/library/cpp/lwtrace/shuttle.h b/library/cpp/lwtrace/shuttle.h index 6950b3877a4..c4519cbb876 100644 --- a/library/cpp/lwtrace/shuttle.h +++ b/library/cpp/lwtrace/shuttle.h @@ -309,7 +309,9 @@ namespace NLWTrace { if (shuttle->IsDead()) { *ref = shuttle->Drop(); } else { - result = result && shuttle->Fork(cHead); + if (Y_UNLIKELY(!shuttle->Fork(cHead))) { + result = false; + } ref = &shuttle->GetNext(); } } diff --git a/library/cpp/lwtrace/trace_ut.cpp b/library/cpp/lwtrace/trace_ut.cpp index 9a29923e28c..5c81a6419a7 100644 --- a/library/cpp/lwtrace/trace_ut.cpp +++ b/library/cpp/lwtrace/trace_ut.cpp @@ -789,6 +789,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) { UNIT_ASSERT(parsed); mngr.New("Query1", q); + mngr.New("Query2", q); { TOrbit a, b, c, d; @@ -849,6 +850,7 @@ Y_UNIT_TEST_SUITE(LWTraceTrace) { } } reader; mngr.ReadDepot("Query1", reader); + mngr.ReadDepot("Query2", reader); } Y_UNIT_TEST(TrackForkError) { diff --git a/library/cpp/yt/logging/benchmark/logger_tag.cpp b/library/cpp/yt/logging/benchmark/logger_tag.cpp new file mode 100644 index 00000000000..cb6208db2a3 --- /dev/null +++ b/library/cpp/yt/logging/benchmark/logger_tag.cpp @@ -0,0 +1,32 @@ +#include <benchmark/benchmark.h> + +#include <library/cpp/yt/logging/logger.h> + +#include <library/cpp/yt/string/format.h> + +#include <library/cpp/yt/misc/guid.h> + +namespace NYT::NLogging { +namespace { + +//////////////////////////////////////////////////////////////////////////////// + +const TGuid RequestId(0x12345678, 0x9abcdef0, 0x11223344, 0x55667788); +const std::string User = "robot-benchmark-user"; +const std::string Realm = "some-realm"; + +void BM_WithTag(benchmark::State& state) +{ + TLogger logger("Benchmark"); + for (auto _ : state) { + auto tagged = logger.WithTag("RequestId: %v, User: %v, Realm: %v", RequestId, User, Realm); + benchmark::DoNotOptimize(tagged); + } +} + +BENCHMARK(BM_WithTag); + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace +} // namespace NYT::NLogging diff --git a/library/cpp/yt/logging/benchmark/ya.make b/library/cpp/yt/logging/benchmark/ya.make new file mode 100644 index 00000000000..61fd0b49276 --- /dev/null +++ b/library/cpp/yt/logging/benchmark/ya.make @@ -0,0 +1,14 @@ +G_BENCHMARK() + +INCLUDE(${ARCADIA_ROOT}/library/cpp/yt/ya_cpp.make.inc) + +SRCS( + logger_tag.cpp +) + +PEERDIR( + library/cpp/yt/logging + library/cpp/yt/string +) + +END() diff --git a/library/cpp/yt/logging/logger-inl.h b/library/cpp/yt/logging/logger-inl.h index e54952822c8..87672ec6f6a 100644 --- a/library/cpp/yt/logging/logger-inl.h +++ b/library/cpp/yt/logging/logger-inl.h @@ -22,9 +22,9 @@ inline bool TLogger::IsAnchorUpToDate(const TLoggingAnchor& anchor) const } template <class... TArgs> -void TLogger::AddTag(const char* format, TArgs&&... args) +void TLogger::AddTag(TFormatString<TArgs...> format, TArgs&&... args) { - AddRawTag(Format(TRuntimeFormat{format}, std::forward<TArgs>(args)...)); + AddRawTag(Format(format, std::forward<TArgs>(args)...)); } template <class TType> @@ -35,7 +35,7 @@ void TLogger::AddStructuredTag(TStringBuf key, TType value) } template <class... TArgs> -TLogger TLogger::WithTag(const char* format, TArgs&&... args) const & +TLogger TLogger::WithTag(TFormatString<TArgs...> format, TArgs&&... args) const & { auto result = *this; result.AddTag(format, std::forward<TArgs>(args)...); @@ -43,7 +43,7 @@ TLogger TLogger::WithTag(const char* format, TArgs&&... args) const & } template <class... TArgs> -TLogger TLogger::WithTag(const char* format, TArgs&&... args) && +TLogger TLogger::WithTag(TFormatString<TArgs...> format, TArgs&&... args) && { AddTag(format, std::forward<TArgs>(args)...); return std::move(*this); diff --git a/library/cpp/yt/logging/logger.cpp b/library/cpp/yt/logging/logger.cpp index 458d01d8133..64d8b06fa7e 100644 --- a/library/cpp/yt/logging/logger.cpp +++ b/library/cpp/yt/logging/logger.cpp @@ -220,23 +220,23 @@ void TLogger::Write(TLogEvent&& event) const LogManager_->Enqueue(std::move(event)); } -void TLogger::AddRawTag(const std::string& tag) +void TLogger::AddRawTag(TStringBuf tag) { auto* state = GetMutableCoWState(); if (!state->Tag.empty()) { state->Tag += ", "; } - state->Tag += tag; + state->Tag.append(tag.data(), tag.size()); } -TLogger TLogger::WithRawTag(const std::string& tag) const & +TLogger TLogger::WithRawTag(TStringBuf tag) const & { auto result = *this; result.AddRawTag(tag); return result; } -TLogger TLogger::WithRawTag(const std::string& tag) && +TLogger TLogger::WithRawTag(TStringBuf tag) && { AddRawTag(tag); return std::move(*this); diff --git a/library/cpp/yt/logging/logger.h b/library/cpp/yt/logging/logger.h index cab385bf676..d781326e88d 100644 --- a/library/cpp/yt/logging/logger.h +++ b/library/cpp/yt/logging/logger.h @@ -227,21 +227,21 @@ public: void Write(TLogEvent&& event) const; - void AddRawTag(const std::string& tag); + void AddRawTag(TStringBuf tag); template <class... TArgs> - void AddTag(const char* format, TArgs&&... args); + void AddTag(TFormatString<TArgs...> format, TArgs&&... args); template <class TType> void AddStructuredTag(TStringBuf key, TType value); void AddStructuredValidator(TStructuredValidator validator); - TLogger WithRawTag(const std::string& tag) const &; - TLogger WithRawTag(const std::string& tag) &&; + TLogger WithRawTag(TStringBuf tag) const &; + TLogger WithRawTag(TStringBuf tag) &&; template <class... TArgs> - TLogger WithTag(const char* format, TArgs&&... args) const &; + TLogger WithTag(TFormatString<TArgs...> format, TArgs&&... args) const &; template <class... TArgs> - TLogger WithTag(const char* format, TArgs&&... args) &&; + TLogger WithTag(TFormatString<TArgs...> format, TArgs&&... args) &&; template <class TType> TLogger WithStructuredTag(TStringBuf key, TType value) const &; diff --git a/library/cpp/yt/logging/ya.make b/library/cpp/yt/logging/ya.make index 8b338ed3b77..b9cf5c6e715 100644 --- a/library/cpp/yt/logging/ya.make +++ b/library/cpp/yt/logging/ya.make @@ -18,6 +18,7 @@ END() RECURSE( backends + benchmark plain_text_formatter ) diff --git a/library/cpp/yt/memory/type_erasure.h b/library/cpp/yt/memory/type_erasure.h index 8d87a347b45..3b2dbe34015 100644 --- a/library/cpp/yt/memory/type_erasure.h +++ b/library/cpp/yt/memory/type_erasure.h @@ -94,7 +94,7 @@ public: T& AnyCast() & { const auto& vtable = GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored<T>()) { + if (!vtable.IsValid() || !vtable.template HoldsType<T>()) { throw TBadAnyCast{}; } @@ -106,7 +106,7 @@ public: const T& AnyCast() const & { const auto& vtable = Holder_.GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored<T>()) { + if (!vtable.IsValid() || !vtable.template HoldsType<T>()) { throw TBadAnyCast{}; } @@ -306,7 +306,7 @@ public: using TWrapped = TOwningWrapper<TDecayed, TStorage, EnableCopy, TCpos...>; const auto& vtable = GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored<TWrapped>()) { + if (!vtable.IsValid() || !vtable.template HoldsType<TWrapped>()) { throw TBadAnyCast{}; } @@ -320,13 +320,23 @@ public: using TWrapped = TOwningWrapper<TDecayed, TStorage, EnableCopy, TCpos...>; const auto& vtable = GetVTable(); - if (!vtable.IsValid() || !vtable.template IsCurrentlyStored<TWrapped>()) { + if (!vtable.IsValid() || !vtable.template HoldsType<TWrapped>()) { throw TBadAnyCast{}; } return Storage_.template As<TWrapped>().Unwrap(); } + template <class T> + Y_FORCE_INLINE bool Holds() const + { + using TDecayed = std::remove_cvref_t<T>; + using TWrapped = TOwningWrapper<TDecayed, TStorage, EnableCopy, TCpos...>; + + const auto& vtable = GetVTable(); + return vtable.IsValid() && vtable.template HoldsType<TWrapped>(); + } + Y_FORCE_INLINE bool IsValid() const { return Holder_.IsValid(); diff --git a/library/cpp/yt/memory/type_erasure_detail.h b/library/cpp/yt/memory/type_erasure_detail.h index 92904573d01..76b611a2d67 100644 --- a/library/cpp/yt/memory/type_erasure_detail.h +++ b/library/cpp/yt/memory/type_erasure_detail.h @@ -304,7 +304,7 @@ public: // NB(arkady-e1ppa): This method may or may not work correctly // for dynamically-linked libraries. template <class T> - Y_FORCE_INLINE bool IsCurrentlyStored() const noexcept + Y_FORCE_INLINE bool HoldsType() const noexcept { return Function_ == &TVTableEntry::StaticInvoke<T>; } @@ -358,9 +358,9 @@ public: } template <class T> - Y_FORCE_INLINE bool IsCurrentlyStored() const noexcept + Y_FORCE_INLINE bool HoldsType() const noexcept { - return TVTableEntry<TStorage, TCpo>::template IsCurrentlyStored<T>(); + return TVTableEntry<TStorage, TCpo>::template HoldsType<T>(); } private: diff --git a/library/cpp/yt/memory/unittests/type_erasure_ut.cpp b/library/cpp/yt/memory/unittests/type_erasure_ut.cpp index b33ab368023..c923ec29a11 100644 --- a/library/cpp/yt/memory/unittests/type_erasure_ut.cpp +++ b/library/cpp/yt/memory/unittests/type_erasure_ut.cpp @@ -23,6 +23,14 @@ struct TCustomized } }; +struct TOtherCustomized +{ + friend int TagInvoke(TTagInvokeTag<TestCpo>, const TOtherCustomized&) + { + return 0; + } +}; + //////////////////////////////////////////////////////////////////////////////// // 2 CPOs won't trigger static vtable. @@ -253,6 +261,22 @@ TEST(TAnyObjectTest, EmptyAny) EXPECT_EQ(conc.Value, 11); } +TEST(TAnyObjectTest, Holds) +{ + using TAnyObject = TAnyObject<TOverload<TestCpo, int(const TErasedThis&)>>; + + TAnyObject any{TCustomized{.Value = 42}}; + EXPECT_TRUE(any.Holds<TCustomized>()); + EXPECT_FALSE(any.Holds<TOtherCustomized>()); + + TAnyObject other{TOtherCustomized{}}; + EXPECT_TRUE(other.Holds<TOtherCustomized>()); + EXPECT_FALSE(other.Holds<TCustomized>()); + + TAnyObject empty; + EXPECT_FALSE(empty.Holds<TCustomized>()); +} + TEST(TAnyObjectTest, CvRefCorrectness) { using TAnyObject = TAnyObject< |
