Add `DynamicCastMessage` overloads for `std::shared_ptr` to replace uses of

`std::dynamic_pointer_cast`.

PiperOrigin-RevId: 686603280
pull/18854/head
Protobuf Team Bot 1 month ago committed by Copybara-Service
parent 9e200bebb2
commit ecec105916
  1. 12
      src/google/protobuf/lite_unittest.cc
  2. 24
      src/google/protobuf/message_lite.h

@ -11,6 +11,7 @@
#include <cstdint>
#include <iostream>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
@ -1381,6 +1382,17 @@ TEST(LiteTest, DynamicCastMessage) {
const MessageLite& test_type_1_pointer_const_ref = test_type_1;
EXPECT_EQ(&test_type_1,
&DynamicCastMessage<CastType1>(test_type_1_pointer_const_ref));
std::shared_ptr<MessageLite> shared(new CastType1);
EXPECT_EQ(1, shared.use_count());
std::shared_ptr<CastType1> shared_1 = DynamicCastMessage<CastType1>(shared);
// Check that both shared_ptr instances are pointing to the same control
// block by checking use_count().
EXPECT_EQ(2, shared.use_count());
EXPECT_EQ(shared_1.get(), shared.get());
std::shared_ptr<CastType2> shared_2 = DynamicCastMessage<CastType2>(shared);
EXPECT_EQ(2, shared.use_count());
EXPECT_EQ(shared_2, nullptr);
}
#if GTEST_HAS_DEATH_TEST

@ -21,9 +21,11 @@
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <memory>
#include <new>
#include <string>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/casts.h"
@ -1438,6 +1440,28 @@ T& DownCastToGenerated(MessageLite& from) {
return DownCastMessage<T>(from);
}
// Overloads for `std::shared_ptr` to substitute `std::dynamic_pointer_cast`
template <typename T>
std::shared_ptr<T> DynamicCastMessage(std::shared_ptr<MessageLite> ptr) {
if (auto* res = DynamicCastMessage<T>(ptr.get())) {
// Use aliasing constructor to keep the same control block.
return std::shared_ptr<T>(std::move(ptr), res);
} else {
return nullptr;
}
}
template <typename T>
std::shared_ptr<const T> DynamicCastMessage(
std::shared_ptr<const MessageLite> ptr) {
if (auto* res = DynamicCastMessage<T>(ptr.get())) {
// Use aliasing constructor to keep the same control block.
return std::shared_ptr<const T>(std::move(ptr), res);
} else {
return nullptr;
}
}
} // namespace protobuf
} // namespace google

Loading…
Cancel
Save