diff options
Diffstat (limited to 'absl/strings')
-rw-r--r-- | absl/strings/internal/str_split_internal.h | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h index 49ec5392..76924771 100644 --- a/absl/strings/internal/str_split_internal.h +++ b/absl/strings/internal/str_split_internal.h @@ -66,41 +66,56 @@ class ConvertibleToStringView { // Matches rvalue strings and moves their data to a member. ConvertibleToStringView(std::string&& s) // NOLINT(runtime/explicit) - : copy_(std::move(s)), value_(copy_) {} + : copy_(std::move(s)), value_(copy_), self_referential_(true) {} ConvertibleToStringView(const ConvertibleToStringView& other) - : copy_(other.copy_), - value_(other.IsSelfReferential() ? copy_ : other.value_) {} + : value_(other.value_), self_referential_(other.self_referential_) { + if (other.self_referential_) { + new (©_) std::string(other.copy_); + value_ = copy_; + } + } - ConvertibleToStringView(ConvertibleToStringView&& other) { - StealMembers(std::move(other)); + ConvertibleToStringView(ConvertibleToStringView&& other) + : value_(other.value_), self_referential_(other.self_referential_) { + if (other.self_referential_) { + new (©_) std::string(std::move(other.copy_)); + value_ = copy_; + } } ConvertibleToStringView& operator=(ConvertibleToStringView other) { - StealMembers(std::move(other)); + this->~ConvertibleToStringView(); + new (this) ConvertibleToStringView(std::move(other)); return *this; } absl::string_view value() const { return value_; } - private: - // Returns true if ctsp's value refers to its internal copy_ member. - bool IsSelfReferential() const { return value_.data() == copy_.data(); } + ~ConvertibleToStringView() { MaybeReleaseCopy(); } - void StealMembers(ConvertibleToStringView&& other) { - if (other.IsSelfReferential()) { - copy_ = std::move(other.copy_); - value_ = copy_; - other.value_ = other.copy_; - } else { - value_ = other.value_; + private: + void MaybeReleaseCopy() { + if (self_referential_) { + // An explicit destructor call cannot be a qualified name such as + // std::string. The "using" declaration works around this + // issue by creating an unqualified name for the destructor. + using string_type = std::string; + copy_.~string_type(); } } - + struct Unused { // MSVC disallows unions with only 1 member. + }; // Holds the data moved from temporary std::string arguments. Declared first // so that 'value' can refer to 'copy_'. - std::string copy_; + union { + std::string copy_; + Unused unused_; + }; + absl::string_view value_; + // true if value_ refers to the internal copy_ member. + bool self_referential_ = false; }; // An iterator that enumerates the parts of a string from a Splitter. The text |