From 77ba7ca9d2a523ef9f1837e53554fa65c232abc8 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 2 Jun 2023 13:49:30 -0700 Subject: Lifetime checks for `absl::StrSplit()` PiperOrigin-RevId: 537400816 Change-Id: I06794a6b8b6a441e34121047024380190d42869a --- absl/strings/internal/str_split_internal.h | 62 +++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'absl/strings/internal/str_split_internal.h') diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h index 35edf3aa..081ad85a 100644 --- a/absl/strings/internal/str_split_internal.h +++ b/absl/strings/internal/str_split_internal.h @@ -235,6 +235,24 @@ struct SplitterIsConvertibleTo HasMappedType::value> { }; +template +struct ShouldUseLifetimeBound : std::false_type {}; + +template +struct ShouldUseLifetimeBound< + StringType, Container, + std::enable_if_t< + std::is_same::value && + std::is_same::value>> + : std::true_type {}; + +template +using ShouldUseLifetimeBoundForPair = std::integral_constant< + bool, std::is_same::value && + (std::is_same::value || + std::is_same::value)>; + + // This class implements the range that is returned by absl::StrSplit(). This // class has templated conversion operators that allow it to be implicitly // converted to a variety of types that the caller may have specified on the @@ -281,10 +299,24 @@ class Splitter { // An implicit conversion operator that is restricted to only those containers // that the splitter is convertible to. - template ::value>::type> - operator Container() const { // NOLINT(runtime/explicit) + template < + typename Container, + std::enable_if_t::value && + SplitterIsConvertibleTo::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator Container() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return ConvertToContainer::value>()(*this); + } + + template < + typename Container, + std::enable_if_t::value && + SplitterIsConvertibleTo::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator Container() const { return ConvertToContainer::value>()(*this); } @@ -293,8 +325,27 @@ class Splitter { // strings returned by the begin() iterator. Either/both of .first and .second // will be constructed with empty strings if the iterator doesn't have a // corresponding value. + template ::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::pair() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return ConvertToPair(); + } + + template ::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::pair() const { + return ConvertToPair(); + } + + private: template - operator std::pair() const { // NOLINT(runtime/explicit) + std::pair ConvertToPair() const { absl::string_view first, second; auto it = begin(); if (it != end()) { @@ -306,7 +357,6 @@ class Splitter { return {First(first), Second(second)}; } - private: // ConvertToContainer is a functor converting a Splitter to the requested // Container of ValueType. It is specialized below to optimize splitting to // certain combinations of Container and ValueType. -- cgit v1.2.3