diff --git a/src/google/protobuf/port.cc b/src/google/protobuf/port.cc index af668e9e2b40e..d60c2b89f5093 100644 --- a/src/google/protobuf/port.cc +++ b/src/google/protobuf/port.cc @@ -97,14 +97,9 @@ void RealDebugCounter::Register(absl::string_view name) { } } -#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT const GlobalEmptyString - fixed_address_empty_string{}; -#else PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GlobalEmptyString fixed_address_empty_string{}; -#endif } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h index 5f9e909a00333..386ecc02a4a92 100644 --- a/src/google/protobuf/port.h +++ b/src/google/protobuf/port.h @@ -494,20 +494,27 @@ class NoopDebugCounter { // Default empty string object. Don't use this directly. Instead, call // GetEmptyString() to get the reference. This empty string is aligned with a // minimum alignment of 8 bytes to match the requirement of ArenaStringPtr. -#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L + // Take advantage of C++20 constexpr support in std::string. -class alignas(8) GlobalEmptyString { +class alignas(8) GlobalEmptyStringConstexpr { public: const std::string& get() const { return value_; } // Nothing to init, or destroy. std::string* Init() const { return nullptr; } + template + static constexpr std::true_type HasConstexprDefaultConstructor(int) { + return {}; + } + static constexpr std::false_type HasConstexprDefaultConstructor(char) { + return {}; + } + private: std::string value_; }; -PROTOBUF_EXPORT extern const GlobalEmptyString fixed_address_empty_string; -#else -class alignas(8) GlobalEmptyString { + +class alignas(8) GlobalEmptyStringDynamicInit { public: const std::string& get() const { return *reinterpret_cast(internal::Launder(buffer_)); @@ -519,8 +526,12 @@ class alignas(8) GlobalEmptyString { private: alignas(std::string) char buffer_[sizeof(std::string)]; }; + +using GlobalEmptyString = std::conditional_t< + GlobalEmptyStringConstexpr::HasConstexprDefaultConstructor(0), + const GlobalEmptyStringConstexpr, GlobalEmptyStringDynamicInit>; + PROTOBUF_EXPORT extern GlobalEmptyString fixed_address_empty_string; -#endif } // namespace internal } // namespace protobuf