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
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.
......
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