diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index c53cbd2..a1610c9 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h
@@ -1011,6 +1011,16 @@ return H::combine_contiguous(std::move(h), a.data(), a.size()); } +template <typename T, size_t N, typename A, typename Predicate> +constexpr typename InlinedVector<T, N, A>::size_type erase_if( + InlinedVector<T, N, A>& v, Predicate pred) { + const auto it = std::remove_if(v.begin(), v.end(), std::move(pred)); + const auto removed = static_cast<typename InlinedVector<T, N, A>::size_type>( + std::distance(it, v.end())); + v.erase(it, v.end()); + return removed; +} + ABSL_NAMESPACE_END } // namespace absl
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc index ff0e77b..ba8c4a8 100644 --- a/absl/container/inlined_vector_test.cc +++ b/absl/container/inlined_vector_test.cc
@@ -51,6 +51,7 @@ using testing::Each; using testing::ElementsAre; using testing::ElementsAreArray; +using testing::IsEmpty; using testing::Eq; using testing::Gt; using testing::Pointee; @@ -2254,4 +2255,22 @@ sizeof(MySpan<int>) / sizeof(int)); } +TEST(IntVec, EraseIf) { + IntVec v = {3, 1, 2, 0}; + EXPECT_EQ(absl::erase_if(v, [](int i) { return i > 1; }), 2u); + EXPECT_THAT(v, ElementsAre(1, 0)); +} + +TEST(IntVec, EraseIfMatchesNone) { + IntVec v = {1, 2, 3}; + EXPECT_EQ(absl::erase_if(v, [](int i) { return i > 10; }), 0u);; + EXPECT_THAT(v, ElementsAre(1, 2, 3)); +} + +TEST(IntVec, EraseIfMatchesAll) { + IntVec v = {1, 2, 3}; + EXPECT_EQ(absl::erase_if(v, [](int i) { return i > 0; }), 3u); + EXPECT_THAT(v, IsEmpty()); +} + } // anonymous namespace
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 679d68c..533886f 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -1175,30 +1175,32 @@ } // General notes on capacity/growth methods below: -// - We use 7/8th as maximum load factor. For 16-wide groups, that gives an -// average of two empty slots per group. -// - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity. +// - We use 27/32 as maximum load factor. For 16-wide groups, that gives an +// average of 2.5 empty slots per group. // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we // never need to probe (the whole table fits in one group) so we don't need a // load factor less than 1. +// - For (capacity+1) == Group::kWidth, growth is capacity - 1 since we need +// at least one empty slot for probing algorithm. +// - For (capacity+1) > Group::kWidth, growth is 27/32*capacity. // Given `capacity`, applies the load factor; i.e., it returns the maximum // number of values we should put into the table before a resizing rehash. constexpr size_t CapacityToGrowth(size_t capacity) { ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity)); - // `capacity*7/8` + // `capacity*27/32` if (Group::kWidth == 8 && capacity == 7) { - // x-x/8 does not work when x==7. + // formula does not work when x==7. return 6; } - return capacity - capacity / 8; + return capacity - capacity / 8 - capacity / 32; } // Given `size`, "unapplies" the load factor to find how large the capacity // should be to stay within the load factor. // // For size == 0, returns 0. -// For other values, returns the same as `NormalizeCapacity(size*8/7)`. +// For other values, returns the same as `NormalizeCapacity(size*32/27)`. constexpr size_t SizeToCapacity(size_t size) { if (size == 0) { return 0; @@ -1207,18 +1209,10 @@ // Shifting right `~size_t{}` by `leading_zeros` yields // NormalizeCapacity(size). int leading_zeros = absl::countl_zero(size); - constexpr size_t kLast3Bits = size_t{7} << (sizeof(size_t) * 8 - 3); - // max_size_for_next_capacity = max_load_factor * next_capacity - // = (7/8) * (~size_t{} >> leading_zeros) - // = (7/8*~size_t{}) >> leading_zeros - // = kLast3Bits >> leading_zeros - size_t max_size_for_next_capacity = kLast3Bits >> leading_zeros; + size_t next_capacity = ~size_t{} >> leading_zeros; + size_t max_size_for_next_capacity = CapacityToGrowth(next_capacity); // Decrease shift if size is too big for the minimum capacity. leading_zeros -= static_cast<int>(size > max_size_for_next_capacity); - if constexpr (Group::kWidth == 8) { - // Formula doesn't work when size==7 for 8-wide groups. - leading_zeros -= (size == 7); - } return (~size_t{}) >> leading_zeros; }
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 044e5b5..d411709 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc
@@ -276,28 +276,53 @@ EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2)); } -TEST(Util, GrowthAndCapacity) { - // Verify that GrowthToCapacity gives the minimum capacity that has enough - // growth. +TEST(Util, SizeToCapacitySmallValues) { EXPECT_EQ(SizeToCapacity(0), 0); EXPECT_EQ(SizeToCapacity(1), 1); EXPECT_EQ(SizeToCapacity(2), 3); EXPECT_EQ(SizeToCapacity(3), 3); + EXPECT_EQ(SizeToCapacity(4), 7); + EXPECT_EQ(SizeToCapacity(5), 7); + EXPECT_EQ(SizeToCapacity(6), 7); + if (Group::kWidth == 16) { + EXPECT_EQ(SizeToCapacity(7), 7); + EXPECT_EQ(SizeToCapacity(14), 15); + } else { + EXPECT_EQ(SizeToCapacity(7), 15); + } +} + +TEST(Util, CapacityToGrowthSmallValues) { + EXPECT_EQ(CapacityToGrowth(1), 1); + EXPECT_EQ(CapacityToGrowth(3), 3); + if (Group::kWidth == 16) { + EXPECT_EQ(CapacityToGrowth(7), 7); + } else { + EXPECT_EQ(CapacityToGrowth(7), 6); + } + EXPECT_EQ(CapacityToGrowth(15), 14); + EXPECT_EQ(CapacityToGrowth(31), 28); + EXPECT_EQ(CapacityToGrowth(63), 55); +} + +TEST(Util, GrowthAndCapacity) { + // Verify that GrowthToCapacity gives the minimum capacity that has enough + // growth. for (size_t growth = 1; growth < 10000; ++growth) { SCOPED_TRACE(growth); size_t capacity = SizeToCapacity(growth); ASSERT_TRUE(IsValidCapacity(capacity)); // The capacity is large enough for `growth`. - EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth)); + ASSERT_THAT(CapacityToGrowth(capacity), Ge(growth)); // For (capacity+1) < kWidth, growth should equal capacity. if (capacity + 1 < Group::kWidth) { - EXPECT_THAT(CapacityToGrowth(capacity), Eq(capacity)); + ASSERT_THAT(CapacityToGrowth(capacity), Eq(capacity)); } else { - EXPECT_THAT(CapacityToGrowth(capacity), Lt(capacity)); + ASSERT_THAT(CapacityToGrowth(capacity), Lt(capacity)); } if (growth != 0 && capacity > 1) { // There is no smaller capacity that works. - EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth)); + ASSERT_THAT(CapacityToGrowth(capacity / 2), Lt(growth)) << capacity; } } @@ -305,9 +330,9 @@ capacity = 2 * capacity + 1) { SCOPED_TRACE(capacity); size_t growth = CapacityToGrowth(capacity); - EXPECT_THAT(growth, Lt(capacity)); - EXPECT_EQ(SizeToCapacity(growth), capacity); - EXPECT_EQ(NormalizeCapacity(SizeToCapacity(growth)), capacity); + ASSERT_THAT(growth, Lt(capacity)); + ASSERT_EQ(SizeToCapacity(growth), capacity); + ASSERT_EQ(NormalizeCapacity(SizeToCapacity(growth)), capacity); } }
diff --git a/absl/crc/internal/crc_x86_arm_combined.cc b/absl/crc/internal/crc_x86_arm_combined.cc index 30cf6a1..ebd9c3f 100644 --- a/absl/crc/internal/crc_x86_arm_combined.cc +++ b/absl/crc/internal/crc_x86_arm_combined.cc
@@ -317,6 +317,46 @@ return crc; } + // Same as Process64BytesCRC, but just interleaved for 2 streams. + ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesCRC2Streams( + const uint8_t* p0, const uint8_t* p1, uint64_t* crc) const { + uint64_t crc0 = crc[0]; + uint64_t crc1 = crc[1]; + for (int i = 0; i < 8; i++) { + crc0 = CRC32_u64(static_cast<uint32_t>(crc0), + absl::little_endian::Load64(p0)); + crc1 = CRC32_u64(static_cast<uint32_t>(crc1), + absl::little_endian::Load64(p1)); + p0 += 8; + p1 += 8; + } + crc[0] = crc0; + crc[1] = crc1; + } + + // Same as Process64BytesCRC, but just interleaved for 3 streams. + ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesCRC3Streams( + const uint8_t* p0, const uint8_t* p1, const uint8_t* p2, + uint64_t* crc) const { + uint64_t crc0 = crc[0]; + uint64_t crc1 = crc[1]; + uint64_t crc2 = crc[2]; + for (int i = 0; i < 8; i++) { + crc0 = CRC32_u64(static_cast<uint32_t>(crc0), + absl::little_endian::Load64(p0)); + crc1 = CRC32_u64(static_cast<uint32_t>(crc1), + absl::little_endian::Load64(p1)); + crc2 = CRC32_u64(static_cast<uint32_t>(crc2), + absl::little_endian::Load64(p2)); + p0 += 8; + p1 += 8; + p2 += 8; + } + crc[0] = crc0; + crc[1] = crc1; + crc[2] = crc2; + } + // Constants generated by './scripts/gen-crc-consts.py x86_pclmul // crc32_lsb_0x82f63b78' from the Linux kernel. alignas(16) static constexpr uint64_t kFoldAcross512Bits[2] = { @@ -452,9 +492,19 @@ uint64_t l64_pclmul[kMaxStreams] = {0}; // Peel first iteration, because PCLMULQDQ stream, needs setup. - for (size_t i = 0; i < num_crc_streams; i++) { - l64_crc[i] = Process64BytesCRC(crc_streams[i], l64_crc[i]); - crc_streams[i] += 16 * 4; + if (num_crc_streams == 1) { + l64_crc[0] = Process64BytesCRC(crc_streams[0], l64_crc[0]); + crc_streams[0] += 16 * 4; + } else if (num_crc_streams == 2) { + Process64BytesCRC2Streams(crc_streams[0], crc_streams[1], l64_crc); + crc_streams[0] += 16 * 4; + crc_streams[1] += 16 * 4; + } else { + Process64BytesCRC3Streams(crc_streams[0], crc_streams[1], + crc_streams[2], l64_crc); + crc_streams[0] += 16 * 4; + crc_streams[1] += 16 * 4; + crc_streams[2] += 16 * 4; } V128 partialCRC[kMaxStreams][4]; @@ -492,24 +542,28 @@ // } // But unrolling and interleaving PCLMULQDQ and CRC blocks manually // gives ~2% performance boost. - l64_crc[0] = Process64BytesCRC(crc_streams[0], l64_crc[0]); - crc_streams[0] += 16 * 4; + if (num_crc_streams == 1) { + l64_crc[0] = Process64BytesCRC(crc_streams[0], l64_crc[0]); + crc_streams[0] += 16 * 4; + } else if (num_crc_streams == 2) { + Process64BytesCRC2Streams(crc_streams[0], crc_streams[1], l64_crc); + crc_streams[0] += 16 * 4; + crc_streams[1] += 16 * 4; + } else { + Process64BytesCRC3Streams(crc_streams[0], crc_streams[1], + crc_streams[2], l64_crc); + crc_streams[0] += 16 * 4; + crc_streams[1] += 16 * 4; + crc_streams[2] += 16 * 4; + } if (num_pclmul_streams > 0) { Process64BytesPclmul(pclmul_streams[0], partialCRC[0]); pclmul_streams[0] += 16 * 4; } - if (num_crc_streams > 1) { - l64_crc[1] = Process64BytesCRC(crc_streams[1], l64_crc[1]); - crc_streams[1] += 16 * 4; - } if (num_pclmul_streams > 1) { Process64BytesPclmul(pclmul_streams[1], partialCRC[1]); pclmul_streams[1] += 16 * 4; } - if (num_crc_streams > 2) { - l64_crc[2] = Process64BytesCRC(crc_streams[2], l64_crc[2]); - crc_streams[2] += 16 * 4; - } if (num_pclmul_streams > 2) { Process64BytesPclmul(pclmul_streams[2], partialCRC[2]); pclmul_streams[2] += 16 * 4;
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc index a693d5c..9e43e94 100644 --- a/absl/hash/internal/hash.cc +++ b/absl/hash/internal/hash.cc
@@ -59,8 +59,7 @@ uint64_t duplicated_state2 = current_state; do { - // Always prefetch the next cacheline. - PrefetchToLocalCache(ptr + ABSL_CACHELINE_SIZE); + PrefetchToLocalCache(ptr + 5 * ABSL_CACHELINE_SIZE); uint64_t a = absl::base_internal::UnalignedLoad64(ptr); uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index ae736b2..775e132 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h
@@ -609,9 +609,15 @@ constexpr uint128 operator>>(uint128 lhs, int amount); constexpr uint128 operator+(uint128 lhs, uint128 rhs); constexpr uint128 operator-(uint128 lhs, uint128 rhs); +#if defined(ABSL_HAVE_INTRINSIC_INT128) +constexpr uint128 operator*(uint128 lhs, uint128 rhs); +constexpr uint128 operator/(uint128 lhs, uint128 rhs); +constexpr uint128 operator%(uint128 lhs, uint128 rhs); +#else // ABSL_HAVE_INTRINSIC_INT128 uint128 operator*(uint128 lhs, uint128 rhs); uint128 operator/(uint128 lhs, uint128 rhs); uint128 operator%(uint128 lhs, uint128 rhs); +#endif // ABSL_HAVE_INTRINSIC_INT128 inline uint128& uint128::operator<<=(int amount) { *this = *this << amount; @@ -1021,19 +1027,15 @@ #endif } +#if !defined(ABSL_HAVE_INTRINSIC_INT128) inline uint128 operator*(uint128 lhs, uint128 rhs) { -#if defined(ABSL_HAVE_INTRINSIC_INT128) - // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 - // can be used for uint128 storage. - return static_cast<unsigned __int128>(lhs) * - static_cast<unsigned __int128>(rhs); -#elif defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC) +#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC) uint64_t carry; uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + Uint128High64(lhs) * Uint128Low64(rhs) + carry, low); -#else // ABSL_HAVE_INTRINSIC128 +#else // _MSC_VER uint64_t a32 = Uint128Low64(lhs) >> 32; uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; uint64_t b32 = Uint128Low64(rhs) >> 32; @@ -1045,16 +1047,24 @@ result += uint128(a32 * b00) << 32; result += uint128(a00 * b32) << 32; return result; -#endif // ABSL_HAVE_INTRINSIC128 +#endif // _MSC_VER } +#endif // ABSL_HAVE_INTRINSIC_INT128 #if defined(ABSL_HAVE_INTRINSIC_INT128) -inline uint128 operator/(uint128 lhs, uint128 rhs) { +constexpr uint128 operator*(uint128 lhs, uint128 rhs) { + // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 + // can be used for uint128 storage. + return static_cast<unsigned __int128>(lhs) * + static_cast<unsigned __int128>(rhs); +} + +constexpr uint128 operator/(uint128 lhs, uint128 rhs) { return static_cast<unsigned __int128>(lhs) / static_cast<unsigned __int128>(rhs); } -inline uint128 operator%(uint128 lhs, uint128 rhs) { +constexpr uint128 operator%(uint128 lhs, uint128 rhs) { return static_cast<unsigned __int128>(lhs) % static_cast<unsigned __int128>(rhs); } @@ -1112,9 +1122,15 @@ constexpr int128 operator-(int128 v); constexpr int128 operator+(int128 lhs, int128 rhs); constexpr int128 operator-(int128 lhs, int128 rhs); +#if defined(ABSL_HAVE_INTRINSIC_INT128) +constexpr int128 operator*(int128 lhs, int128 rhs); +constexpr int128 operator/(int128 lhs, int128 rhs); +constexpr int128 operator%(int128 lhs, int128 rhs); +#else int128 operator*(int128 lhs, int128 rhs); int128 operator/(int128 lhs, int128 rhs); int128 operator%(int128 lhs, int128 rhs); +#endif // ABSL_HAVE_INTRINSIC_INT128 constexpr int128 operator|(int128 lhs, int128 rhs); constexpr int128 operator&(int128 lhs, int128 rhs); constexpr int128 operator^(int128 lhs, int128 rhs);
diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc index 216115a..62eb045 100644 --- a/absl/numeric/int128_have_intrinsic.inc +++ b/absl/numeric/int128_have_intrinsic.inc
@@ -254,17 +254,19 @@ return static_cast<__int128>(lhs) - static_cast<__int128>(rhs); } -inline int128 operator*(int128 lhs, int128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) +constexpr int128 operator*(int128 lhs, int128 rhs) { return static_cast<__int128>(lhs) * static_cast<__int128>(rhs); } -inline int128 operator/(int128 lhs, int128 rhs) { +constexpr int128 operator/(int128 lhs, int128 rhs) { return static_cast<__int128>(lhs) / static_cast<__int128>(rhs); } -inline int128 operator%(int128 lhs, int128 rhs) { +constexpr int128 operator%(int128 lhs, int128 rhs) { return static_cast<__int128>(lhs) % static_cast<__int128>(rhs); } +#endif // ABSL_HAVE_INTRINSIC_INT128 inline int128 int128::operator++(int) { int128 tmp(*this);
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc index 13a0e7f..1712af8 100644 --- a/absl/numeric/int128_test.cc +++ b/absl/numeric/int128_test.cc
@@ -350,7 +350,7 @@ c = a * b; EXPECT_EQ(absl::MakeUint128(0x530EDA741C71D4C3, 0xBF25975319080000), c); EXPECT_EQ(0, c - b * a); - EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); + EXPECT_EQ(a * a - b * b, (a + b) * (a - b)); // Verified with dc. a = absl::MakeUint128(0x0123456789abcdef, 0xfedcba9876543210); @@ -358,7 +358,7 @@ c = a * b; EXPECT_EQ(absl::MakeUint128(0x97a87f4f261ba3f2, 0x342d0bbf48948200), c); EXPECT_EQ(0, c - b * a); - EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); + EXPECT_EQ(a * a - b * b, (a + b) * (a - b)); } TEST(Uint128, AliasTests) { @@ -462,6 +462,17 @@ EXPECT_EQ(zero, absl::uint128(0)); EXPECT_EQ(one, absl::uint128(1)); EXPECT_EQ(minus_two, absl::MakeUint128(-1, -2)); + +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr absl::uint128 division = absl::uint128(10) / absl::uint128(2); + EXPECT_EQ(division, absl::uint128(5)); + + constexpr absl::uint128 modulus = absl::int128(10) % absl::int128(3); + EXPECT_EQ(modulus, absl::uint128(1)); + + constexpr absl::uint128 multiplication = absl::uint128(10) * absl::uint128(3); + EXPECT_EQ(multiplication, absl::uint128(30)); +#endif // ABSL_HAVE_INTRINSIC_INT128 } TEST(Uint128, NumericLimitsTest) { @@ -522,7 +533,6 @@ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(values)); } - TEST(Int128Uint128, ConversionTest) { absl::int128 nonnegative_signed_values[] = { 0, @@ -540,8 +550,7 @@ } absl::int128 negative_values[] = { - -1, -0x1234567890abcdef, - absl::MakeInt128(-0x5544332211ffeedd, 0), + -1, -0x1234567890abcdef, absl::MakeInt128(-0x5544332211ffeedd, 0), -absl::MakeInt128(0x76543210fedcba98, 0xabcdef0123456789)}; for (absl::int128 value : negative_values) { EXPECT_EQ(absl::uint128(-value), -absl::uint128(value)); @@ -769,6 +778,17 @@ EXPECT_EQ(minus_two, absl::MakeInt128(-1, -2)); EXPECT_GT(max, one); EXPECT_LT(min, minus_two); + +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr absl::int128 division = absl::int128(10) / absl::int128(2); + EXPECT_EQ(division, absl::int128(5)); + + constexpr absl::int128 modulus = absl::int128(10) % absl::int128(3); + EXPECT_EQ(modulus, absl::int128(1)); + + constexpr absl::int128 multiplication = absl::int128(10) * absl::int128(3); + EXPECT_EQ(multiplication, absl::int128(30)); +#endif // ABSL_HAVE_INTRINSIC_INT128 } TEST(Int128, ComparisonTest) {
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc index b083975..c17c472 100644 --- a/absl/strings/str_split_test.cc +++ b/absl/strings/str_split_test.cc
@@ -216,7 +216,7 @@ std::multimap<std::string, std::string> m = absl::StrSplit("a,1,b,2,a,3", ','); EXPECT_EQ(3, m.size()); - auto it = m.find("a"); + auto it = m.lower_bound("a"); EXPECT_EQ("1", it->second); ++it; EXPECT_EQ("3", it->second);
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index 1dc04c5..aaaf60b 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h
@@ -34,7 +34,9 @@ #include <iosfwd> #include <iterator> #include <limits> +#include <memory> #include <string> +#include <type_traits> #include "absl/base/attributes.h" #include "absl/base/nullability.h" @@ -208,6 +210,16 @@ ABSL_ASSERT(data != nullptr || len == 0); } +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + template <std::contiguous_iterator It, std::sized_sentinel_for<It> End> + requires(std::is_same_v<std::iter_value_t<It>, value_type> && + !std::is_convertible_v<End, size_type>) + constexpr string_view(It begin, End end) + : ptr_(std::to_address(begin)), length_(end - begin) { + ABSL_HARDENING_ASSERT(end >= begin); + } +#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + constexpr string_view(const string_view&) noexcept = default; string_view& operator=(const string_view&) noexcept = default;
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index adf4d1b..c5d15c7 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc
@@ -16,6 +16,7 @@ #include <stdlib.h> +#include <array> #include <cstddef> #include <cstdlib> #include <cstring> @@ -131,6 +132,23 @@ EXPECT_EQ(8u, s31.length()); } +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + { + // Iterator constructor + std::string str = "hello"; + absl::string_view s1(str.begin(), str.end()); + EXPECT_EQ(s1, "hello"); + + std::array<char, 3> arr = { '1', '2', '3' }; + absl::string_view s2(arr.begin(), arr.end()); + EXPECT_EQ(s2, "123"); + + const char carr[] = "carr"; + absl::string_view s3(carr, carr + strlen(carr)); + EXPECT_EQ(s3, "carr"); + } +#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + { using mstring = std::basic_string<char, std::char_traits<char>, Mallocator<char>>; @@ -1154,6 +1172,18 @@ constexpr size_t sp_npos = sp.npos; EXPECT_EQ(sp_npos, static_cast<size_t>(-1)); + +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + { + static constexpr std::array<char, 3> arr = { '1', '2', '3' }; + constexpr absl::string_view s2(arr.begin(), arr.end()); + EXPECT_EQ(s2, "123"); + + static constexpr char carr[] = "carr"; + constexpr absl::string_view s3(carr, carr + 4); + EXPECT_EQ(s3, "carr"); + } +#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L } constexpr char ConstexprMethodsHelper() {