diff options
author | Abseil Team <absl-team@google.com> | 2020-06-17 14:16:51 -0700 |
---|---|---|
committer | Andy Getz <durandal@google.com> | 2020-06-18 16:10:44 -0400 |
commit | 4ccc0fce09836a25b474f4b1453146dae2c29f4d (patch) | |
tree | eb4e2c17bd7a605337192b21af4e9fe694b6e429 /absl/strings/internal | |
parent | 4a851046a0102cd986a5714a1af8deef28a544c4 (diff) |
Export of internal Abseil changes
--
34c0d521b11ed4191ea3e071a864a84e5e5941b7 by Matthew Brown <matthewbr@google.com>:
Release absl::StrFormat custom type extensions
- Allows StrFormat methods to be extended to accept types which implement
AbslFormatConvert()
- NOLINTNEXTLINE(readability-redundant-declaration) used, declarations are
required in some compilers.
PiperOrigin-RevId: 316963065
--
4d475b5ad02d41057447d722ad35573fc4f48d1f by Evan Brown <ezb@google.com>:
Small fix to previous change: the first overload of insert_iterator_unique wasn't actually being selected. Fix that issue and add tests to verify that it actually works.
Note: couldn't use TestInstanceTracker here because that counts instances (and decrements in destructor) rather than counting all constructor calls.
PiperOrigin-RevId: 316927690
GitOrigin-RevId: 34c0d521b11ed4191ea3e071a864a84e5e5941b7
Change-Id: If8bbb8317b93af4084ac4cc55b752b99b1581b58
Diffstat (limited to 'absl/strings/internal')
-rw-r--r-- | absl/strings/internal/str_format/arg.h | 34 | ||||
-rw-r--r-- | absl/strings/internal/str_format/arg_test.cc | 10 | ||||
-rw-r--r-- | absl/strings/internal/str_format/extension.cc | 23 | ||||
-rw-r--r-- | absl/strings/internal/str_format/extension.h | 6 | ||||
-rw-r--r-- | absl/strings/internal/str_format/extension_test.cc | 15 |
5 files changed, 82 insertions, 6 deletions
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index d441e87f..3dbc1526 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -25,10 +25,12 @@ class Cord; class FormatCountCapture; class FormatSink; -namespace str_format_internal { - +template <absl::FormatConversionCharSet C> +struct FormatConvertResult; class FormatConversionSpec; +namespace str_format_internal { + template <typename T, typename = void> struct HasUserDefinedConvert : std::false_type {}; @@ -39,6 +41,22 @@ struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert( std::declval<FormatSink*>()))>> : std::true_type {}; +void AbslFormatConvert(); // Stops the lexical name lookup +template <typename T> +auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv, + FormatSinkImpl* sink) + -> decltype(AbslFormatConvert(v, + std::declval<const FormatConversionSpec&>(), + std::declval<FormatSink*>())) { + using FormatConversionSpecT = + absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>; + using FormatSinkT = + absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>; + auto fcs = conv.Wrap<FormatConversionSpecT>(); + auto fs = sink->Wrap<FormatSinkT>(); + return AbslFormatConvert(v, fcs, &fs); +} + template <typename T> class StreamedWrapper; @@ -46,6 +64,13 @@ class StreamedWrapper; // then convert it, appending to `sink` and return `true`. // Otherwise fail and return `false`. +// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v' +// as an extension mechanism. These FormatConvertImpl functions are the default +// implementations. +// The ADL search is augmented via the 'Sink*' parameter, which also +// serves as a disambiguator to reject possible unintended 'AbslFormatConvert' +// functions in the namespaces associated with 'v'. + // Raw pointers. struct VoidPtr { VoidPtr() = default; @@ -62,6 +87,11 @@ struct ArgConvertResult { }; template <FormatConversionCharSet C> +constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) { + return C; +} + +template <FormatConversionCharSet C> constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) { return C; } diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc index bf3d7e8e..f53fd6bd 100644 --- a/absl/strings/internal/str_format/arg_test.cc +++ b/absl/strings/internal/str_format/arg_test.cc @@ -23,8 +23,17 @@ class FormatArgImplTest : public ::testing::Test { enum Color { kRed, kGreen, kBlue }; static const char *hi() { return "hi"; } + + struct X {}; + + X x_; }; +inline FormatConvertResult<FormatConversionCharSet{}> AbslFormatConvert( + const FormatArgImplTest::X &, const FormatConversionSpec &, FormatSink *) { + return {false}; +} + TEST_F(FormatArgImplTest, ToInt) { int out = 0; EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(1), &out)); @@ -59,6 +68,7 @@ TEST_F(FormatArgImplTest, ToInt) { FormatArgImpl(static_cast<int *>(nullptr)), &out)); EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(hi()), &out)); EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl("hi"), &out)); + EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(x_), &out)); EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(kBlue), &out)); EXPECT_EQ(2, out); } diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc index 94f2b9c2..bb0d96cf 100644 --- a/absl/strings/internal/str_format/extension.cc +++ b/absl/strings/internal/str_format/extension.cc @@ -33,6 +33,29 @@ std::string Flags::ToString() const { return s; } +#define ABSL_INTERNAL_X_VAL(id) \ + constexpr absl::FormatConversionChar FormatConversionCharInternal::id; +ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, ) +#undef ABSL_INTERNAL_X_VAL +// NOLINTNEXTLINE(readability-redundant-declaration) +constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone; + +#define ABSL_INTERNAL_CHAR_SET_CASE(c) \ + constexpr FormatConversionCharSet FormatConversionCharSetInternal::c; +ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, ) +#undef ABSL_INTERNAL_CHAR_SET_CASE + +// NOLINTNEXTLINE(readability-redundant-declaration) +constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar; +// NOLINTNEXTLINE(readability-redundant-declaration) +constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral; +// NOLINTNEXTLINE(readability-redundant-declaration) +constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating; +// NOLINTNEXTLINE(readability-redundant-declaration) +constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric; +// NOLINTNEXTLINE(readability-redundant-declaration) +constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer; + bool FormatSinkImpl::PutPaddedString(string_view value, int width, int precision, bool left) { size_t space_remaining = 0; diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index 6c60c6c3..a9b9e137 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -31,11 +31,11 @@ namespace absl { ABSL_NAMESPACE_BEGIN -namespace str_format_internal { - enum class FormatConversionChar : uint8_t; enum class FormatConversionCharSet : uint64_t; +namespace str_format_internal { + class FormatRawSinkImpl { public: // Implicitly convert from any type that provides the hook function as @@ -361,14 +361,12 @@ struct FormatConversionCharSetInternal { static constexpr FormatConversionCharSet kStar = FormatConversionCharToConvValue('*'); - // Some predefined values (TODO(matthewbr), delete any that are unused). static constexpr FormatConversionCharSet kIntegral = FormatConversionCharSetUnion(d, i, u, o, x, X); static constexpr FormatConversionCharSet kFloating = FormatConversionCharSetUnion(a, e, f, g, A, E, F, G); static constexpr FormatConversionCharSet kNumeric = FormatConversionCharSetUnion(kIntegral, kFloating); - static constexpr FormatConversionCharSet kString = s; static constexpr FormatConversionCharSet kPointer = p; }; diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc index 0a023f9c..1c93fdb1 100644 --- a/absl/strings/internal/str_format/extension_test.cc +++ b/absl/strings/internal/str_format/extension_test.cc @@ -80,4 +80,19 @@ TEST(FormatExtensionTest, SinkAppendChars) { EXPECT_EQ(actual, expected); } } + +TEST(FormatExtensionTest, VerifyEnumEquality) { +#define X_VAL(id) \ + EXPECT_EQ(absl::FormatConversionChar::id, \ + absl::str_format_internal::FormatConversionCharInternal::id); + ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, ); +#undef X_VAL + +#define X_VAL(id) \ + EXPECT_EQ(absl::FormatConversionCharSet::id, \ + absl::str_format_internal::FormatConversionCharSetInternal::id); + ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, ); +#undef X_VAL +} + } // namespace |