diff options
Diffstat (limited to 'absl')
-rw-r--r-- | absl/log/internal/log_message.h | 14 | ||||
-rw-r--r-- | absl/strings/BUILD.bazel | 13 | ||||
-rw-r--r-- | absl/strings/CMakeLists.txt | 13 | ||||
-rw-r--r-- | absl/strings/has_absl_stringify.h | 63 | ||||
-rw-r--r-- | absl/strings/has_absl_stringify_test.cc | 37 | ||||
-rw-r--r-- | absl/strings/internal/has_absl_stringify.h | 21 | ||||
-rw-r--r-- | absl/strings/internal/str_format/arg.h | 15 | ||||
-rw-r--r-- | absl/strings/str_cat.h | 14 | ||||
-rw-r--r-- | absl/strings/substitute.h | 4 |
9 files changed, 152 insertions, 42 deletions
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h index 46937728..c94d0530 100644 --- a/absl/log/internal/log_message.h +++ b/absl/log/internal/log_message.h @@ -40,7 +40,7 @@ #include "absl/log/internal/nullguard.h" #include "absl/log/log_entry.h" #include "absl/log/log_sink.h" -#include "absl/strings/internal/has_absl_stringify.h" +#include "absl/strings/has_absl_stringify.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" @@ -170,15 +170,13 @@ class LogMessage { // Types that support `AbslStringify()` are serialized that way. template <typename T, - typename std::enable_if< - strings_internal::HasAbslStringify<T>::value, int>::type = 0> + typename std::enable_if<HasAbslStringify<T>::value, int>::type = 0> LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE; // Types that don't support `AbslStringify()` but do support streaming into a // `std::ostream&` are serialized that way. template <typename T, - typename std::enable_if< - !strings_internal::HasAbslStringify<T>::value, int>::type = 0> + typename std::enable_if<!HasAbslStringify<T>::value, int>::type = 0> LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE; // Note: We explicitly do not support `operator<<` for non-const references @@ -283,8 +281,7 @@ class StringifySink final { // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` template <typename T, - typename std::enable_if<strings_internal::HasAbslStringify<T>::value, - int>::type> + typename std::enable_if<HasAbslStringify<T>::value, int>::type> LogMessage& LogMessage::operator<<(const T& v) { StringifySink sink(*this); // Replace with public API. @@ -294,8 +291,7 @@ LogMessage& LogMessage::operator<<(const T& v) { // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` template <typename T, - typename std::enable_if<!strings_internal::HasAbslStringify<T>::value, - int>::type> + typename std::enable_if<!HasAbslStringify<T>::value, int>::type> LogMessage& LogMessage::operator<<(const T& v) { OstreamView view(*data_); view.stream() << log_internal::NullGuard<T>().Guard(v); diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index e226a27d..6d0ed698 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -70,6 +70,7 @@ cc_library( "ascii.h", "charconv.h", "escaping.h", + "has_absl_stringify.h", "internal/damerau_levenshtein_distance.h", "internal/has_absl_stringify.h", "internal/string_constant.h", @@ -180,6 +181,18 @@ cc_test( ) cc_test( + name = "has_absl_stringify_test", + size = "small", + srcs = ["has_absl_stringify_test.cc"], + copts = ABSL_TEST_COPTS, + visibility = ["//visibility:private"], + deps = [ + ":strings", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( name = "ascii_test", size = "small", srcs = ["ascii_test.cc"], diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 8bd93271..ebf085db 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -38,6 +38,7 @@ absl_cc_library( "ascii.h" "charconv.h" "escaping.h" + "has_absl_stringify.h" "internal/damerau_levenshtein_distance.h" "internal/string_constant.h" "internal/has_absl_stringify.h" @@ -156,6 +157,18 @@ absl_cc_test( absl_cc_test( NAME + has_absl_stringify_test + SRCS + "has_absl_stringify_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::strings + GTest::gmock_main +) + +absl_cc_test( + NAME ascii_test SRCS "ascii_test.cc" diff --git a/absl/strings/has_absl_stringify.h b/absl/strings/has_absl_stringify.h new file mode 100644 index 00000000..274a7865 --- /dev/null +++ b/absl/strings/has_absl_stringify.h @@ -0,0 +1,63 @@ +// Copyright 2022 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_ +#define ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_ + +#include <type_traits> +#include <utility> + +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +namespace strings_internal { + +// This is an empty class not intended to be used. It exists so that +// `HasAbslStringify` can reference a universal class rather than needing to be +// copied for each new sink. +class UnimplementedSink { + public: + void Append(size_t count, char ch); + + void Append(string_view v); + + // Support `absl::Format(&sink, format, args...)`. + friend void AbslFormatFlush(UnimplementedSink* sink, absl::string_view v); +}; + +} // namespace strings_internal + +// `HasAbslStringify<T>` detects if type `T` supports the `AbslStringify()` +// customization point (see +// https://abseil.io/docs/cpp/guides/format#abslstringify for the +// documentation). +// +// Note that there are types that can be `StrCat`-ed that do not use the +// `AbslStringify` customization point (for example, `int`). + +template <typename T, typename = void> +struct HasAbslStringify : std::false_type {}; + +template <typename T> +struct HasAbslStringify< + T, std::enable_if_t<std::is_void<decltype(AbslStringify( + std::declval<strings_internal::UnimplementedSink&>(), + std::declval<const T&>()))>::value>> : std::true_type {}; + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_ diff --git a/absl/strings/has_absl_stringify_test.cc b/absl/strings/has_absl_stringify_test.cc new file mode 100644 index 00000000..e9915c66 --- /dev/null +++ b/absl/strings/has_absl_stringify_test.cc @@ -0,0 +1,37 @@ +// Copyright 2023 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/strings/has_absl_stringify.h" + +#include <string> + +#include "gtest/gtest.h" + +namespace { + +struct TypeWithoutAbslStringify {}; + +struct TypeWithAbslStringify { + template <typename Sink> + friend void AbslStringify(Sink&, const TypeWithAbslStringify&) {} +}; + +TEST(HasAbslStringifyTest, Works) { + EXPECT_FALSE(absl::HasAbslStringify<int>::value); + EXPECT_FALSE(absl::HasAbslStringify<std::string>::value); + EXPECT_FALSE(absl::HasAbslStringify<TypeWithoutAbslStringify>::value); + EXPECT_TRUE(absl::HasAbslStringify<TypeWithAbslStringify>::value); +} + +} // namespace diff --git a/absl/strings/internal/has_absl_stringify.h b/absl/strings/internal/has_absl_stringify.h index 55a08508..5eaddad1 100644 --- a/absl/strings/internal/has_absl_stringify.h +++ b/absl/strings/internal/has_absl_stringify.h @@ -18,31 +18,20 @@ #include <type_traits> #include <utility> -#include "absl/strings/string_view.h" +#include "absl/base/attributes.h" +#include "absl/strings/has_absl_stringify.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace strings_internal { -// This is an empty class not intended to be used. It exists so that -// `HasAbslStringify` can reference a universal class rather than needing to be -// copied for each new sink. -class UnimplementedSink { - public: - void Append(size_t count, char ch); - - void Append(string_view v); - - // Support `absl::Format(&sink, format, args...)`. - friend void AbslFormatFlush(UnimplementedSink* sink, absl::string_view v); -}; - template <typename T, typename = void> -struct HasAbslStringify : std::false_type {}; +struct ABSL_DEPRECATED("Use absl::HasAbslStringify") HasAbslStringify + : std::false_type {}; template <typename T> -struct HasAbslStringify< +struct ABSL_DEPRECATED("Use absl::HasAbslStringify") HasAbslStringify< T, std::enable_if_t<std::is_void<decltype(AbslStringify( std::declval<strings_internal::UnimplementedSink&>(), std::declval<const T&>()))>::value>> : std::true_type {}; diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 3ce30feb..2e017549 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -31,7 +31,7 @@ #include "absl/base/port.h" #include "absl/meta/type_traits.h" #include "absl/numeric/int128.h" -#include "absl/strings/internal/has_absl_stringify.h" +#include "absl/strings/has_absl_stringify.h" #include "absl/strings/internal/str_format/extension.h" #include "absl/strings/string_view.h" @@ -333,7 +333,7 @@ IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv, template <typename T> typename std::enable_if<std::is_enum<T>::value && !HasUserDefinedConvert<T>::value && - !strings_internal::HasAbslStringify<T>::value, + !HasAbslStringify<T>::value, IntegralConvertResult>::type FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); @@ -447,7 +447,7 @@ class FormatArgImpl { struct DecayType { static constexpr bool kHasUserDefined = str_format_internal::HasUserDefinedConvert<T>::value || - strings_internal::HasAbslStringify<T>::value; + HasAbslStringify<T>::value; using type = typename std::conditional< !kHasUserDefined && std::is_convertible<T, const char*>::value, const char*, @@ -456,11 +456,10 @@ class FormatArgImpl { VoidPtr, const T&>::type>::type; }; template <typename T> - struct DecayType<T, - typename std::enable_if< - !str_format_internal::HasUserDefinedConvert<T>::value && - !strings_internal::HasAbslStringify<T>::value && - std::is_enum<T>::value>::type> { + struct DecayType< + T, typename std::enable_if< + !str_format_internal::HasUserDefinedConvert<T>::value && + !HasAbslStringify<T>::value && std::is_enum<T>::value>::type> { using type = decltype(+typename std::underlying_type<T>::type()); }; diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index 554c89de..e7823683 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h @@ -102,7 +102,7 @@ #include "absl/base/attributes.h" #include "absl/base/port.h" #include "absl/meta/type_traits.h" -#include "absl/strings/internal/has_absl_stringify.h" +#include "absl/strings/has_absl_stringify.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/stringify_sink.h" #include "absl/strings/numbers.h" @@ -357,7 +357,7 @@ class AlphaNum { : piece_(pc) {} template <typename T, typename = typename std::enable_if< - strings_internal::HasAbslStringify<T>::value>::type> + HasAbslStringify<T>::value>::type> AlphaNum( // NOLINT(runtime/explicit) const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND, strings_internal::StringifySink&& sink ABSL_ATTRIBUTE_LIFETIME_BOUND = {}) @@ -384,17 +384,17 @@ class AlphaNum { template <typename T, typename = typename std::enable_if< std::is_enum<T>{} && std::is_convertible<T, int>{} && - !strings_internal::HasAbslStringify<T>::value>::type> + !HasAbslStringify<T>::value>::type> AlphaNum(T e) // NOLINT(runtime/explicit) : AlphaNum(+e) {} // This overload matches scoped enums. We must explicitly cast to the // underlying type, but use integral promotion for the same reason as above. template <typename T, - typename std::enable_if< - std::is_enum<T>{} && !std::is_convertible<T, int>{} && - !strings_internal::HasAbslStringify<T>::value, - char*>::type = nullptr> + typename std::enable_if<std::is_enum<T>{} && + !std::is_convertible<T, int>{} && + !HasAbslStringify<T>::value, + char*>::type = nullptr> AlphaNum(T e) // NOLINT(runtime/explicit) : AlphaNum(+static_cast<typename std::underlying_type<T>::type>(e)) {} diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index d6a5a690..0d6cb7c7 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -176,7 +176,7 @@ class Arg { : piece_(value ? "true" : "false") {} template <typename T, typename = typename std::enable_if< - strings_internal::HasAbslStringify<T>::value>::type> + HasAbslStringify<T>::value>::type> Arg( // NOLINT(google-explicit-constructor) const T& v, strings_internal::StringifySink&& sink = {}) : piece_(strings_internal::ExtractStringification(sink, v)) {} @@ -204,7 +204,7 @@ class Arg { template <typename T, typename = typename std::enable_if< std::is_enum<T>{} && !std::is_convertible<T, int>{} && - !strings_internal::HasAbslStringify<T>::value>::type> + !HasAbslStringify<T>::value>::type> Arg(T value) // NOLINT(google-explicit-constructor) : Arg(static_cast<typename std::underlying_type<T>::type>(value)) {} |