mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Add conversion operator to std::array for StrSplit.
This is similar to the conversion operator to std::pair, but for N elements instead of two. Missing elements are filled with the empty string and extra elements are discarded. PiperOrigin-RevId: 693727220 Change-Id: Icfee16613a4859b019ca043da712f20797386beb
This commit is contained in:
committed by
Copybara-Service
parent
4794821d8b
commit
e83ef27968
@@ -253,6 +253,10 @@ using ShouldUseLifetimeBoundForPair = std::integral_constant<
|
||||
(std::is_same<First, absl::string_view>::value ||
|
||||
std::is_same<Second, absl::string_view>::value)>;
|
||||
|
||||
template <typename StringType, typename ElementType, std::size_t Size>
|
||||
using ShouldUseLifetimeBoundForArray = std::integral_constant<
|
||||
bool, std::is_same<StringType, std::string>::value &&
|
||||
std::is_same<ElementType, 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
|
||||
@@ -344,7 +348,38 @@ class Splitter {
|
||||
return ConvertToPair<First, Second>();
|
||||
}
|
||||
|
||||
// Returns an array with its elements set to the first few strings returned by
|
||||
// the begin() iterator. If there is not a corresponding value the empty
|
||||
// string is used.
|
||||
template <typename ElementType, std::size_t Size,
|
||||
std::enable_if_t<ShouldUseLifetimeBoundForArray<
|
||||
StringType, ElementType, Size>::value,
|
||||
std::nullptr_t> = nullptr>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator std::array<ElementType, Size>() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
return ConvertToArray<ElementType, Size>();
|
||||
}
|
||||
|
||||
template <typename ElementType, std::size_t Size,
|
||||
std::enable_if_t<!ShouldUseLifetimeBoundForArray<
|
||||
StringType, ElementType, Size>::value,
|
||||
std::nullptr_t> = nullptr>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator std::array<ElementType, Size>() const {
|
||||
return ConvertToArray<ElementType, Size>();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename ElementType, std::size_t Size>
|
||||
std::array<ElementType, Size> ConvertToArray() const {
|
||||
std::array<ElementType, Size> a;
|
||||
auto it = begin();
|
||||
for (std::size_t i = 0; i < Size && it != end(); ++i, ++it) {
|
||||
a[i] = ElementType(*it);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename First, typename Second>
|
||||
std::pair<First, Second> ConvertToPair() const {
|
||||
absl::string_view first, second;
|
||||
|
||||
@@ -444,8 +444,10 @@ using EnableSplitIfString =
|
||||
// behavior works for:
|
||||
//
|
||||
// 1) All standard STL containers including `std::vector`, `std::list`,
|
||||
// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
|
||||
// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`.
|
||||
// 2) `std::pair` (which is not actually a container). See below.
|
||||
// 3) `std::array`, which is a container but has different behavior due to its
|
||||
// fixed size. See below.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
@@ -487,6 +489,21 @@ using EnableSplitIfString =
|
||||
// std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
|
||||
// // p.first == "a", p.second == "b" // "c" is omitted.
|
||||
//
|
||||
//
|
||||
// Splitting to `std::array` is similar to splitting to `std::pair`, but for
|
||||
// N elements instead of two; missing elements are filled with the empty string
|
||||
// and extra elements are discarded.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// // Stores first two split strings as the elements in a std::array.
|
||||
// std::array<std::string, 2> a = absl::StrSplit("a,b,c", ',');
|
||||
// // a[0] == "a", a[1] == "b" // "c" is omitted.
|
||||
//
|
||||
// // The second element is empty.
|
||||
// std::array<std::string, 2> a = absl::StrSplit("a,", ',');
|
||||
// // a[0] == "a", a[1] == ""
|
||||
//
|
||||
// The `StrSplit()` function can be used multiple times to perform more
|
||||
// complicated splitting logic, such as intelligently parsing key-value pairs.
|
||||
//
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "absl/strings/str_split.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
@@ -397,6 +398,12 @@ void TestPairConversionOperator(const Splitter& splitter) {
|
||||
EXPECT_EQ(p, (std::pair<FirstType, SecondType>("a", "b")));
|
||||
}
|
||||
|
||||
template <typename StringType, typename Splitter>
|
||||
void TestArrayConversionOperator(const Splitter& splitter) {
|
||||
std::array<StringType, 2> a = splitter;
|
||||
EXPECT_THAT(a, ElementsAre("a", "b"));
|
||||
}
|
||||
|
||||
TEST(Splitter, ConversionOperator) {
|
||||
auto splitter = absl::StrSplit("a,b,c,d", ',');
|
||||
|
||||
@@ -467,6 +474,10 @@ TEST(Splitter, ConversionOperator) {
|
||||
TestPairConversionOperator<absl::string_view, std::string>(splitter);
|
||||
TestPairConversionOperator<std::string, absl::string_view>(splitter);
|
||||
TestPairConversionOperator<std::string, std::string>(splitter);
|
||||
|
||||
// Tests conversion to std::array
|
||||
TestArrayConversionOperator<std::string>(splitter);
|
||||
TestArrayConversionOperator<absl::string_view>(splitter);
|
||||
}
|
||||
|
||||
// A few additional tests for conversion to std::pair. This conversion is
|
||||
@@ -511,6 +522,41 @@ TEST(Splitter, ToPair) {
|
||||
}
|
||||
}
|
||||
|
||||
// std::array tests similar to std::pair tests above, testing fewer, exactly,
|
||||
// or more elements than the array size.
|
||||
TEST(Splitter, ToArray) {
|
||||
{
|
||||
// Empty string
|
||||
std::array<std::string, 2> p = absl::StrSplit("", ',');
|
||||
EXPECT_THAT(p, ElementsAre("", ""));
|
||||
}
|
||||
|
||||
{
|
||||
// Only first
|
||||
std::array<std::string, 2> p = absl::StrSplit("a", ',');
|
||||
EXPECT_THAT(p, ElementsAre("a", ""));
|
||||
}
|
||||
|
||||
{
|
||||
// Only second
|
||||
std::array<std::string, 2> p = absl::StrSplit(",b", ',');
|
||||
EXPECT_THAT(p, ElementsAre("", "b"));
|
||||
}
|
||||
|
||||
{
|
||||
// First and second.
|
||||
std::array<std::string, 2> p = absl::StrSplit("a,b", ',');
|
||||
EXPECT_THAT(p, ElementsAre("a", "b"));
|
||||
}
|
||||
|
||||
{
|
||||
// First and second and then more stuff that will be ignored.
|
||||
std::array<std::string, 2> p = absl::StrSplit("a,b,c", ',');
|
||||
EXPECT_THAT(p, ElementsAre("a", "b"));
|
||||
// "c" is omitted.
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Splitter, Predicates) {
|
||||
static const char kTestChars[] = ",a, ,b,";
|
||||
using absl::AllowEmpty;
|
||||
|
||||
Reference in New Issue
Block a user