Commit 77ba7ca9 by Abseil Team Committed by Copybara-Service

Lifetime checks for `absl::StrSplit()`

PiperOrigin-RevId: 537400816
Change-Id: I06794a6b8b6a441e34121047024380190d42869a
parent 55de7357
...@@ -235,6 +235,24 @@ struct SplitterIsConvertibleTo ...@@ -235,6 +235,24 @@ struct SplitterIsConvertibleTo
HasMappedType<C>::value> { 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 // This class implements the range that is returned by absl::StrSplit(). This
// class has templated conversion operators that allow it to be implicitly // 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 // converted to a variety of types that the caller may have specified on the
...@@ -281,10 +299,24 @@ class Splitter { ...@@ -281,10 +299,24 @@ class Splitter {
// An implicit conversion operator that is restricted to only those containers // An implicit conversion operator that is restricted to only those containers
// that the splitter is convertible to. // that the splitter is convertible to.
template <typename Container, template <
typename = typename std::enable_if< typename Container,
SplitterIsConvertibleTo<Container>::value>::type> std::enable_if_t<ShouldUseLifetimeBound<StringType, Container>::value &&
operator Container() const { // NOLINT(runtime/explicit) 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, return ConvertToContainer<Container, typename Container::value_type,
HasMappedType<Container>::value>()(*this); HasMappedType<Container>::value>()(*this);
} }
...@@ -293,8 +325,27 @@ class Splitter { ...@@ -293,8 +325,27 @@ class Splitter {
// strings returned by the begin() iterator. Either/both of .first and .second // 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 // will be constructed with empty strings if the iterator doesn't have a
// corresponding value. // 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> 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; absl::string_view first, second;
auto it = begin(); auto it = begin();
if (it != end()) { if (it != end()) {
...@@ -306,7 +357,6 @@ class Splitter { ...@@ -306,7 +357,6 @@ class Splitter {
return {First(first), Second(second)}; return {First(first), Second(second)};
} }
private:
// ConvertToContainer is a functor converting a Splitter to the requested // ConvertToContainer is a functor converting a Splitter to the requested
// Container of ValueType. It is specialized below to optimize splitting to // Container of ValueType. It is specialized below to optimize splitting to
// certain combinations of Container and ValueType. // certain combinations of Container and ValueType.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment