diff options
Diffstat (limited to 'absl/strings')
-rw-r--r-- | absl/strings/internal/str_split_internal.h | 62 |
1 files changed, 56 insertions, 6 deletions
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<C>::value> { }; +template <typename StringType, typename Container, typename = void> +struct ShouldUseLifetimeBound : std::false_type {}; + +template <typename StringType, typename Container> +struct ShouldUseLifetimeBound< + StringType, Container, + std::enable_if_t< + std::is_same<StringType, std::string>::value && + std::is_same<typename Container::value_type, absl::string_view>::value>> + : std::true_type {}; + +template <typename StringType, typename First, typename Second> +using ShouldUseLifetimeBoundForPair = std::integral_constant< + bool, std::is_same<StringType, std::string>::value && + (std::is_same<First, absl::string_view>::value || + std::is_same<Second, absl::string_view>::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 <typename Container, - typename = typename std::enable_if< - SplitterIsConvertibleTo<Container>::value>::type> - operator Container() const { // NOLINT(runtime/explicit) + template < + typename Container, + std::enable_if_t<ShouldUseLifetimeBound<StringType, Container>::value && + SplitterIsConvertibleTo<Container>::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator Container() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return ConvertToContainer<Container, typename Container::value_type, + HasMappedType<Container>::value>()(*this); + } + + template < + typename Container, + std::enable_if_t<!ShouldUseLifetimeBound<StringType, Container>::value && + SplitterIsConvertibleTo<Container>::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator Container() const { return ConvertToContainer<Container, typename Container::value_type, HasMappedType<Container>::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 <typename First, typename Second, + std::enable_if_t< + ShouldUseLifetimeBoundForPair<StringType, First, Second>::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::pair<First, Second>() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return ConvertToPair<First, Second>(); + } + + template <typename First, typename Second, + std::enable_if_t<!ShouldUseLifetimeBoundForPair<StringType, First, + Second>::value, + std::nullptr_t> = nullptr> + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::pair<First, Second>() const { + return ConvertToPair<First, Second>(); + } + + private: template <typename First, typename Second> - operator std::pair<First, Second>() const { // NOLINT(runtime/explicit) + std::pair<First, Second> 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. |