Merge branch 'abseil:master' into patch-1

pull/1285/head
Randolf J 2 years ago committed by GitHub
commit beaec23379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      absl/base/internal/thread_annotations.h
  2. 3
      absl/container/BUILD.bazel
  3. 3
      absl/container/CMakeLists.txt
  4. 15
      absl/container/internal/common_policy_traits.h
  5. 9
      absl/container/internal/common_policy_traits_test.cc
  6. 13
      absl/container/internal/container_memory.h
  7. 27
      absl/container/internal/raw_hash_set_test.cc
  8. 5
      absl/hash/CMakeLists.txt
  9. 1
      absl/log/internal/log_sink_set.cc
  10. 6
      absl/log/log_entry.h
  11. 5
      absl/strings/BUILD.bazel
  12. 2
      absl/strings/CMakeLists.txt
  13. 106
      absl/strings/charconv.cc
  14. 1
      absl/strings/cord_test.cc
  15. 5
      absl/strings/str_cat.h
  16. 18
      absl/strings/str_cat_test.cc
  17. 5
      absl/strings/str_format.h
  18. 17
      absl/strings/str_format_test.cc
  19. 62
      absl/types/internal/variant.h

@ -38,6 +38,13 @@
#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
// ABSL_LEGACY_THREAD_ANNOTATIONS is a *temporary* compatibility macro that can
// be defined on the compile command-line to restore the legacy spellings of the
// thread annotations macros/functions. The macros in this file are available
// under ABSL_ prefixed spellings in absl/base/thread_annotations.h. This macro
// and the legacy spellings will be removed in the future.
#ifdef ABSL_LEGACY_THREAD_ANNOTATIONS
#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
@ -268,4 +275,6 @@ inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
} // namespace thread_safety_analysis
#endif // defined(ABSL_LEGACY_THREAD_ANNOTATIONS)
#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_

@ -637,6 +637,8 @@ cc_test(
],
deps = [
":container_memory",
":flat_hash_map",
":flat_hash_set",
":hash_function_defaults",
":hash_policy_testing",
":hashtable_debug",
@ -646,6 +648,7 @@ cc_test(
"//absl/base:core_headers",
"//absl/base:prefetch",
"//absl/base:raw_logging_internal",
"//absl/log",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],

@ -722,12 +722,15 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::container_memory
absl::flat_hash_map
absl::flat_hash_set
absl::hash_function_defaults
absl::hash_policy_testing
absl::hashtable_debug
absl::raw_hash_set
absl::base
absl::config
absl::log
absl::core_headers
absl::prefetch
absl::raw_logging_internal

@ -16,6 +16,7 @@
#define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
#include <cstddef>
#include <cstring>
#include <memory>
#include <new>
#include <type_traits>
@ -32,7 +33,8 @@ template <class Policy, class = void>
struct common_policy_traits {
// The actual object stored in the container.
using slot_type = typename Policy::slot_type;
using reference = decltype(Policy::element(std::declval<slot_type*>()));
using value_type = typename std::remove_reference<reference>::type;
// PRECONDITION: `slot` is UNINITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
@ -89,6 +91,17 @@ struct common_policy_traits {
template <class Alloc>
static void transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, char) {
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
if (absl::is_trivially_relocatable<value_type>()) {
// TODO(b/247130232): remove cast after fixing class-memaccess warning.
std::memcpy(static_cast<void*>(
std::launder(const_cast<std::remove_const_t<value_type>*>(
&element(new_slot)))),
&element(old_slot), sizeof(value_type));
return;
}
#endif
construct(alloc, new_slot, std::move(element(old_slot)));
destroy(alloc, old_slot);
}

@ -27,7 +27,7 @@ namespace container_internal {
namespace {
using ::testing::MockFunction;
using ::testing::Return;
using ::testing::AnyNumber;
using ::testing::ReturnRef;
using Slot = int;
@ -101,9 +101,10 @@ TEST_F(Test, element) {
TEST_F(Test, without_transfer) {
int b = 42;
EXPECT_CALL(element, Call(&b)).WillOnce(::testing::ReturnRef(b));
EXPECT_CALL(construct, Call(&alloc, &a, b));
EXPECT_CALL(destroy, Call(&alloc, &b));
EXPECT_CALL(element, Call(&a)).Times(AnyNumber()).WillOnce(ReturnRef(a));
EXPECT_CALL(element, Call(&b)).WillOnce(ReturnRef(b));
EXPECT_CALL(construct, Call(&alloc, &a, b)).Times(AnyNumber());
EXPECT_CALL(destroy, Call(&alloc, &b)).Times(AnyNumber());
common_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b);
}

@ -17,6 +17,7 @@
#include <cassert>
#include <cstddef>
#include <cstring>
#include <memory>
#include <new>
#include <tuple>
@ -340,7 +341,8 @@ template <class K, class V>
struct map_slot_policy {
using slot_type = map_slot_type<K, V>;
using value_type = std::pair<const K, V>;
using mutable_value_type = std::pair<K, V>;
using mutable_value_type =
std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
private:
static void emplace(slot_type* slot) {
@ -424,6 +426,15 @@ struct map_slot_policy {
static void transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
emplace(new_slot);
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
if (absl::is_trivially_relocatable<value_type>()) {
// TODO(b/247130232): remove cast after fixing class-memaccess warning.
std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),
&old_slot->value, sizeof(value_type));
return;
}
#endif
if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::construct(
*alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));

@ -14,17 +14,25 @@
#include "absl/container/internal/raw_hash_set.h"
#include <algorithm>
#include <atomic>
#include <cmath>
#include <cstdint>
#include <deque>
#include <functional>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <ostream>
#include <random>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@ -33,10 +41,13 @@
#include "absl/base/internal/cycleclock.h"
#include "absl/base/internal/prefetch.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_function_defaults.h"
#include "absl/container/internal/hash_policy_testing.h"
#include "absl/container/internal/hashtable_debug.h"
#include "absl/log/log.h"
#include "absl/strings/string_view.h"
namespace absl {
@ -339,7 +350,7 @@ class StringPolicy {
struct ctor {};
template <class... Ts>
slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {}
explicit slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {}
std::pair<std::string, std::string> pair;
};
@ -411,7 +422,7 @@ struct CustomAlloc : std::allocator<T> {
CustomAlloc() {}
template <typename U>
CustomAlloc(const CustomAlloc<U>& other) {}
explicit CustomAlloc(const CustomAlloc<U>& /*other*/) {}
template<class U> struct rebind {
using other = CustomAlloc<U>;
@ -1275,6 +1286,7 @@ TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {
for (size_t size : sizes) {
auto& stat = stats[size];
VerifyStats(size, expected, stat);
LOG(INFO) << size << " " << stat;
}
}
@ -1370,6 +1382,7 @@ TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {
for (size_t size : sizes) {
auto& stat = stats[size];
VerifyStats(size, expected, stat);
LOG(INFO) << size << " " << stat;
}
}
@ -1504,7 +1517,7 @@ TEST(Table, RehashZeroForcesRehash) {
TEST(Table, ConstructFromInitList) {
using P = std::pair<std::string, std::string>;
struct Q {
operator P() const { return {}; }
operator P() const { return {}; } // NOLINT
};
StringTable t = {P(), Q(), {}, {{}, {}}};
}
@ -2027,7 +2040,7 @@ TEST(Table, UnstablePointers) {
TEST(TableDeathTest, EraseOfEndAsserts) {
// Use an assert with side-effects to figure out if they are actually enabled.
bool assert_enabled = false;
assert([&]() {
assert([&]() { // NOLINT
assert_enabled = true;
return true;
}());
@ -2047,7 +2060,7 @@ TEST(RawHashSamplerTest, Sample) {
auto& sampler = GlobalHashtablezSampler();
size_t start_size = 0;
std::unordered_set<const HashtablezInfo*> preexisting_info;
absl::flat_hash_set<const HashtablezInfo*> preexisting_info;
start_size += sampler.Iterate([&](const HashtablezInfo& info) {
preexisting_info.insert(&info);
++start_size;
@ -2074,8 +2087,8 @@ TEST(RawHashSamplerTest, Sample) {
}
}
size_t end_size = 0;
std::unordered_map<size_t, int> observed_checksums;
std::unordered_map<ssize_t, int> reservations;
absl::flat_hash_map<size_t, int> observed_checksums;
absl::flat_hash_map<ssize_t, int> reservations;
end_size += sampler.Iterate([&](const HashtablezInfo& info) {
if (preexisting_info.count(&info) == 0) {
observed_checksums[info.hashes_bitwise_xor.load(

@ -82,6 +82,10 @@ absl_cc_test(
)
# Internal-only target, do not depend on directly.
#
# Note: Even though external code should not depend on this target
# directly, it must be marked PUBLIC since it is a dependency of
# hash_testing.
absl_cc_library(
NAME
spy_hash_state
@ -94,6 +98,7 @@ absl_cc_library(
absl::strings
absl::str_format
TESTONLY
PUBLIC
)
# Internal-only target, do not depend on directly.

@ -69,6 +69,7 @@ bool& ThreadIsLoggingStatus() {
}
return true;
}();
(void)unused; // Fixes -wunused-variable warning
bool* thread_is_logging_ptr =
reinterpret_cast<bool*>(pthread_getspecific(thread_is_logging_key));

@ -58,8 +58,10 @@ class LogEntry final {
static constexpr int kNoVerbosityLevel = -1;
static constexpr int kNoVerboseLevel = -1; // TO BE removed
LogEntry(const LogEntry&) = default;
LogEntry& operator=(const LogEntry&) = default;
// Pass `LogEntry` by reference, and do not store it as its state does not
// outlive the call to `LogSink::Send()`.
LogEntry(const LogEntry&) = delete;
LogEntry& operator=(const LogEntry&) = delete;
// Source file and line where the log message occurred. Taken from `__FILE__`
// and `__LINE__` unless overridden by `LOG(...).AtLocation(...)`.

@ -747,13 +747,13 @@ cc_test(
":cordz_test_helpers",
":str_format",
":strings",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/base:raw_logging_internal",
"//absl/container:fixed_array",
"//absl/hash",
"//absl/log",
"//absl/random",
"@com_google_googletest//:gtest_main",
],
@ -963,8 +963,8 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
":str_format",
":strings",
"//absl/base:core_headers",
"@com_google_googletest//:gtest_main",
],
)
@ -1164,7 +1164,6 @@ cc_test(
":cord",
":str_format",
":strings",
"//absl/base:core_headers",
"@com_google_googletest//:gtest_main",
],
)

@ -281,6 +281,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::strings
absl::str_format
absl::core_headers
GTest::gmock_main
)
@ -903,6 +904,7 @@ absl_cc_library(
absl::cord_internal
absl::strings
TESTONLY
PUBLIC
)
# Internal-only target, do not depend on directly.

@ -229,6 +229,8 @@ struct FloatTraits<float> {
//
// 2**63 <= Power10Mantissa(n) < 2**64.
//
// See the "Table of powers of 10" comment below for a "1e60" example.
//
// Lookups into the power-of-10 table must first check the Power10Overflow() and
// Power10Underflow() functions, to avoid out-of-bounds table access.
//
@ -236,7 +238,6 @@ struct FloatTraits<float> {
// indexes range from kPower10TableMinInclusive to kPower10TableMaxExclusive.
extern const uint64_t kPower10MantissaHighTable[]; // High 64 of 128 bits.
extern const uint64_t kPower10MantissaLowTable[]; // Low 64 of 128 bits.
extern const int16_t kPower10ExponentTable[];
// The smallest (inclusive) allowed value for use with the Power10Mantissa()
// and Power10Exponent() functions below. (If a smaller exponent is needed in
@ -253,7 +254,11 @@ uint64_t Power10Mantissa(int n) {
}
int Power10Exponent(int n) {
return kPower10ExponentTable[n - kPower10TableMinInclusive];
// The 217706 etc magic numbers encode the results as a formula instead of a
// table. Their equivalence (over the kPower10TableMinInclusive ..
// kPower10TableMaxExclusive range) is confirmed by
// https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go
return (217706 * n >> 16) - 63;
}
// Returns true if n is large enough that 10**n always results in an IEEE
@ -698,9 +703,7 @@ bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative,
// (+) Normalization.
int clz = countl_zero(man);
man <<= static_cast<unsigned int>(clz);
// The 217706 etc magic numbers encode the kPower10ExponentTable as a formula
// instead of a table. Their equivalence is confirmed by
// https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go
// The 217706 etc magic numbers are from the Power10Exponent function.
uint64_t ret_exp2 =
static_cast<uint64_t>((217706 * exp10 >> 16) + 64 +
FloatTraits<FloatType>::kExponentBias - clz);
@ -935,13 +938,33 @@ namespace {
// kPower10MantissaHighTable[i - kPower10TableMinInclusive] stores the 64-bit
// mantissa. The high bit is always on.
//
// kPower10ExponentTable[i - kPower10TableMinInclusive] stores the power-of-two
// exponent.
// kPower10MantissaLowTable extends that 64-bit mantissa to 128 bits.
//
// For a given number i, this gives the unique mantissa and exponent such that
// (mantissa * 2**exponent) <= 10**i < ((mantissa + 1) * 2**exponent).
// Power10Exponent(i) calculates the power-of-two exponent.
//
// kPower10MantissaLowTable extends that 64-bit mantissa to 128 bits.
// For a number i, this gives the unique mantissaHigh and exponent such that
// (mantissaHigh * 2**exponent) <= 10**i < ((mantissaHigh + 1) * 2**exponent).
//
// For example, Python can confirm that the exact hexadecimal value of 1e60 is:
// >>> a = 1000000000000000000000000000000000000000000000000000000000000
// >>> hex(a)
// '0x9f4f2726179a224501d762422c946590d91000000000000000'
// Adding underscores at every 8th hex digit shows 50 hex digits:
// '0x9f4f2726_179a2245_01d76242_2c946590_d9100000_00000000_00'.
// In this case, the high bit of the first hex digit, 9, is coincidentally set,
// so we do not have to do further shifting to deduce the 128-bit mantissa:
// - kPower10MantissaHighTable[60 - kP10TMI] = 0x9f4f2726179a2245U
// - kPower10MantissaLowTable[ 60 - kP10TMI] = 0x01d762422c946590U
// where kP10TMI is kPower10TableMinInclusive. The low 18 of those 50 hex
// digits are truncated.
//
// 50 hex digits (with the high bit set) is 200 bits and mantissaHigh holds 64
// bits, so Power10Exponent(60) = 200 - 64 = 136. Again, Python can confirm:
// >>> b = 0x9f4f2726179a2245
// >>> ((b+0)<<136) <= a
// True
// >>> ((b+1)<<136) <= a
// False
//
// The tables were generated by
// https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go
@ -1388,69 +1411,6 @@ const uint64_t kPower10MantissaLowTable[] = {
0xe0133fe4adf8e952U, 0x58180fddd97723a6U, 0x570f09eaa7ea7648U,
};
const int16_t kPower10ExponentTable[] = {
-1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173, -1170, -1166,
-1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140, -1136, -1133, -1130,
-1127, -1123, -1120, -1117, -1113, -1110, -1107, -1103, -1100, -1097, -1093,
-1090, -1087, -1083, -1080, -1077, -1073, -1070, -1067, -1063, -1060, -1057,
-1053, -1050, -1047, -1043, -1040, -1037, -1034, -1030, -1027, -1024, -1020,
-1017, -1014, -1010, -1007, -1004, -1000, -997, -994, -990, -987, -984,
-980, -977, -974, -970, -967, -964, -960, -957, -954, -950, -947,
-944, -940, -937, -934, -931, -927, -924, -921, -917, -914, -911,
-907, -904, -901, -897, -894, -891, -887, -884, -881, -877, -874,
-871, -867, -864, -861, -857, -854, -851, -847, -844, -841, -838,
-834, -831, -828, -824, -821, -818, -814, -811, -808, -804, -801,
-798, -794, -791, -788, -784, -781, -778, -774, -771, -768, -764,
-761, -758, -754, -751, -748, -744, -741, -738, -735, -731, -728,
-725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691,
-688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655,
-651, -648, -645, -642, -638, -635, -632, -628, -625, -622, -618,
-615, -612, -608, -605, -602, -598, -595, -592, -588, -585, -582,
-578, -575, -572, -568, -565, -562, -558, -555, -552, -549, -545,
-542, -539, -535, -532, -529, -525, -522, -519, -515, -512, -509,
-505, -502, -499, -495, -492, -489, -485, -482, -479, -475, -472,
-469, -465, -462, -459, -455, -452, -449, -446, -442, -439, -436,
-432, -429, -426, -422, -419, -416, -412, -409, -406, -402, -399,
-396, -392, -389, -386, -382, -379, -376, -372, -369, -366, -362,
-359, -356, -353, -349, -346, -343, -339, -336, -333, -329, -326,
-323, -319, -316, -313, -309, -306, -303, -299, -296, -293, -289,
-286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253,
-250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216,
-213, -210, -206, -203, -200, -196, -193, -190, -186, -183, -180,
-176, -173, -170, -166, -163, -160, -157, -153, -150, -147, -143,
-140, -137, -133, -130, -127, -123, -120, -117, -113, -110, -107,
-103, -100, -97, -93, -90, -87, -83, -80, -77, -73, -70,
-67, -63, -60, -57, -54, -50, -47, -44, -40, -37, -34,
-30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3,
6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 39,
43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 76,
79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113,
116, 119, 123, 126, 129, 132, 136, 139, 142, 146, 149,
152, 156, 159, 162, 166, 169, 172, 176, 179, 182, 186,
189, 192, 196, 199, 202, 206, 209, 212, 216, 219, 222,
226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259,
262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295,
299, 302, 305, 309, 312, 315, 319, 322, 325, 328, 332,
335, 338, 342, 345, 348, 352, 355, 358, 362, 365, 368,
372, 375, 378, 382, 385, 388, 392, 395, 398, 402, 405,
408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441,
445, 448, 451, 455, 458, 461, 465, 468, 471, 475, 478,
481, 485, 488, 491, 495, 498, 501, 505, 508, 511, 515,
518, 521, 524, 528, 531, 534, 538, 541, 544, 548, 551,
554, 558, 561, 564, 568, 571, 574, 578, 581, 584, 588,
591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624,
627, 631, 634, 637, 641, 644, 647, 651, 654, 657, 661,
664, 667, 671, 674, 677, 681, 684, 687, 691, 694, 697,
701, 704, 707, 711, 714, 717, 720, 724, 727, 730, 734,
737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770,
774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807,
810, 813, 817, 820, 823, 827, 830, 833, 837, 840, 843,
847, 850, 853, 857, 860, 863, 867, 870, 873, 877, 880,
883, 887, 890, 893, 897, 900, 903, 907, 910, 913, 916,
920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953,
956, 960,
};
} // namespace
ABSL_NAMESPACE_END
} // namespace absl

@ -28,7 +28,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/raw_logging.h"

@ -85,6 +85,11 @@ class StringifySink {
bool PutPaddedString(string_view v, int width, int precision, bool left);
// Support `absl::Format(&sink, format, args...)`.
friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {
sink->Append(v);
}
template <typename T>
friend string_view ExtractStringification(StringifySink& sink, const T& v);

@ -21,6 +21,7 @@
#include <vector>
#include "gtest/gtest.h"
#include "absl/strings/str_format.h"
#include "absl/strings/substitute.h"
#ifdef __ANDROID__
@ -632,4 +633,21 @@ TEST(StrCat, AbslStringifyExample) {
EXPECT_EQ(absl::StrCat("a ", p, " z"), "a (10, 20) z");
}
struct PointStringifyUsingFormat {
template <typename FormatSink>
friend void AbslStringify(FormatSink& sink,
const PointStringifyUsingFormat& p) {
absl::Format(&sink, "(%g, %g)", p.x, p.y);
}
double x = 10.0;
double y = 20.0;
};
TEST(StrCat, AbslStringifyExampleUsingFormat) {
PointStringifyUsingFormat p;
EXPECT_EQ(absl::StrCat(p), "(10, 20)");
EXPECT_EQ(absl::StrCat("a ", p, " z"), "a (10, 20) z");
}
} // namespace

@ -789,6 +789,11 @@ class FormatSink {
return sink_->PutPaddedString(v, width, precision, left);
}
// Support `absl::Format(&sink, format, args...)`.
friend void AbslFormatFlush(FormatSink* sink, absl::string_view v) {
sink->Append(v);
}
private:
friend str_format_internal::FormatSinkImpl;
explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}

@ -1118,6 +1118,23 @@ TEST_F(FormatExtensionTest, AbslStringifyExample) {
PointStringify p;
EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
}
struct PointStringifyUsingFormat {
template <typename FormatSink>
friend void AbslStringify(FormatSink& sink,
const PointStringifyUsingFormat& p) {
absl::Format(&sink, "(%g, %g)", p.x, p.y);
}
double x = 10.0;
double y = 20.0;
};
TEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) {
PointStringifyUsingFormat p;
EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
}
} // namespace
// Some codegen thunks that we can use to easily dump the generated assembly for

@ -449,7 +449,7 @@ struct FlattenIndices;
template <std::size_t HeadSize, std::size_t... TailSize>
struct FlattenIndices<HeadSize, TailSize...> {
template<class... SizeType>
template <class... SizeType>
static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
}
@ -498,8 +498,8 @@ struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
};
template <class Op, class... SizeType>
static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(
Op&& op, SizeType... i) {
static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(Op&& op,
SizeType... i) {
return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
FlattenedOp<Op>{absl::forward<Op>(op)},
FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
@ -683,13 +683,13 @@ struct VariantCoreAccess {
variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
void operator()(SizeT<NewIndex::value> /*old_i*/
) const {
) const {
Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other);
}
template <std::size_t OldIndex>
void operator()(SizeT<OldIndex> /*old_i*/
) const {
) const {
using New =
typename absl::variant_alternative<NewIndex::value, Left>::type;
if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
@ -868,18 +868,6 @@ struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
template <class Self, std::size_t I>
struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
template <class Variant, class T, class = void>
struct ConversionIsPossibleImpl : std::false_type {};
template <class Variant, class T>
struct ConversionIsPossibleImpl<
Variant, T,
void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
: std::true_type {};
template <class Variant, class T>
struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
template <class Variant, class T>
struct IndexOfConstructedType<
Variant, T,
@ -1151,16 +1139,16 @@ struct VariantHelper<variant<Ts...>> {
// Type metafunction which returns the element type selected if
// OverloadSet::Overload() is well-formed when called with argument type U.
template <typename U>
using BestMatch = decltype(
variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>()));
using BestMatch = decltype(variant_internal::OverloadSet<Ts...>::Overload(
std::declval<U>()));
// Type metafunction which returns true if OverloadSet::Overload() is
// well-formed when called with argument type U.
// CanAccept can't be just an alias because there is a MSVC bug on parameter
// pack expansion involving decltype.
template <typename U>
struct CanAccept :
std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
struct CanAccept
: std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
// Type metafunction which returns true if Other is an instantiation of
// variant, and variants's converting constructor from Other will be
@ -1183,8 +1171,8 @@ struct TrivialMoveOnly {
// A union's defaulted copy/move constructor is deleted if any variant member's
// copy/move constructor is nontrivial.
template <typename T>
struct IsTriviallyMoveConstructible:
std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
struct IsTriviallyMoveConstructible
: std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
// To guarantee triviality of all special-member functions that can be trivial,
// we use a chain of conditional bases for each one.
@ -1419,14 +1407,14 @@ class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
VariantMoveAssignBaseNontrivial& operator=(
VariantMoveAssignBaseNontrivial const&) = default;
VariantMoveAssignBaseNontrivial&
operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
absl::conjunction<std::is_nothrow_move_constructible<T>...,
std::is_nothrow_move_assignable<T>...>::value) {
VisitIndices<sizeof...(T)>::Run(
VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
return *this;
}
VariantMoveAssignBaseNontrivial&
operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
absl::conjunction<std::is_nothrow_move_constructible<T>...,
std::is_nothrow_move_assignable<T>...>::value) {
VisitIndices<sizeof...(T)>::Run(
VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
return *this;
}
protected:
using Base::index_;
@ -1450,12 +1438,12 @@ class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
VariantCopyAssignBaseNontrivial& operator=(
VariantCopyAssignBaseNontrivial&&) = default;
VariantCopyAssignBaseNontrivial& operator=(
const VariantCopyAssignBaseNontrivial& other) {
VisitIndices<sizeof...(T)>::Run(
VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
return *this;
}
VariantCopyAssignBaseNontrivial& operator=(
const VariantCopyAssignBaseNontrivial& other) {
VisitIndices<sizeof...(T)>::Run(
VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
return *this;
}
protected:
using Base::index_;

Loading…
Cancel
Save