Skip to content

Commit db8cd47

Browse files
Abseil Teamcopybara-github
authored andcommitted
Add support for enum types with AbslStringify
PiperOrigin-RevId: 487394692 Change-Id: I55e9b57055483dc921e9773c3643ea9be4f9bdf6
1 parent 1687dbf commit db8cd47

File tree

4 files changed

+34
-3
lines changed

4 files changed

+34
-3
lines changed

absl/strings/internal/str_format/arg.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,20 @@
1818
#include <string.h>
1919
#include <wchar.h>
2020

21+
#include <algorithm>
2122
#include <cstdio>
2223
#include <iomanip>
2324
#include <limits>
2425
#include <memory>
2526
#include <sstream>
2627
#include <string>
2728
#include <type_traits>
29+
#include <utility>
2830

2931
#include "absl/base/port.h"
3032
#include "absl/meta/type_traits.h"
3133
#include "absl/numeric/int128.h"
34+
#include "absl/strings/internal/has_absl_stringify.h"
3235
#include "absl/strings/internal/str_format/extension.h"
3336
#include "absl/strings/string_view.h"
3437

@@ -271,7 +274,8 @@ IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
271274
// FormatArgImpl will use the underlying Convert functions instead.
272275
template <typename T>
273276
typename std::enable_if<std::is_enum<T>::value &&
274-
!HasUserDefinedConvert<T>::value,
277+
!HasUserDefinedConvert<T>::value &&
278+
!strings_internal::HasAbslStringify<T>::value,
275279
IntegralConvertResult>::type
276280
FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
277281

@@ -384,7 +388,8 @@ class FormatArgImpl {
384388
template <typename T, typename = void>
385389
struct DecayType {
386390
static constexpr bool kHasUserDefined =
387-
str_format_internal::HasUserDefinedConvert<T>::value;
391+
str_format_internal::HasUserDefinedConvert<T>::value ||
392+
strings_internal::HasAbslStringify<T>::value;
388393
using type = typename std::conditional<
389394
!kHasUserDefined && std::is_convertible<T, const char*>::value,
390395
const char*,
@@ -396,6 +401,7 @@ class FormatArgImpl {
396401
struct DecayType<T,
397402
typename std::enable_if<
398403
!str_format_internal::HasUserDefinedConvert<T>::value &&
404+
!strings_internal::HasAbslStringify<T>::value &&
399405
std::is_enum<T>::value>::type> {
400406
using type = typename std::underlying_type<T>::type;
401407
};

absl/strings/str_cat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ class AlphaNum {
318318
// This overload matches only scoped enums.
319319
template <typename T,
320320
typename = typename std::enable_if<
321-
std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
321+
std::is_enum<T>{} && !std::is_convertible<T, int>{} &&
322+
!strings_internal::HasAbslStringify<T>::value>::type>
322323
AlphaNum(T e) // NOLINT(runtime/explicit)
323324
: AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
324325

absl/strings/str_cat_test.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,4 +650,16 @@ TEST(StrCat, AbslStringifyExampleUsingFormat) {
650650
EXPECT_EQ(absl::StrCat("a ", p, " z"), "a (10, 20) z");
651651
}
652652

653+
enum class EnumWithStringify { Many = 0, Choices = 1 };
654+
655+
template <typename Sink>
656+
void AbslStringify(Sink& sink, EnumWithStringify e) {
657+
absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices");
658+
}
659+
660+
TEST(StrCat, AbslStringifyWithEnum) {
661+
const auto e = EnumWithStringify::Choices;
662+
EXPECT_EQ(absl::StrCat(e), "Choices");
663+
}
664+
653665
} // namespace

absl/strings/str_format_test.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,18 @@ TEST_F(FormatExtensionTest, AbslStringifyExampleUsingFormat) {
11351135
EXPECT_EQ(absl::StrFormat("a %v z", p), "a (10, 20) z");
11361136
}
11371137

1138+
enum class EnumWithStringify { Many = 0, Choices = 1 };
1139+
1140+
template <typename Sink>
1141+
void AbslStringify(Sink& sink, EnumWithStringify e) {
1142+
absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices");
1143+
}
1144+
1145+
TEST_F(FormatExtensionTest, AbslStringifyWithEnum) {
1146+
const auto e = EnumWithStringify::Choices;
1147+
EXPECT_EQ(absl::StrFormat("My choice is %v", e), "My choice is Choices");
1148+
}
1149+
11381150
} // namespace
11391151

11401152
// Some codegen thunks that we can use to easily dump the generated assembly for

0 commit comments

Comments
 (0)