aboutsummaryrefslogtreecommitdiff
path: root/absl/strings/str_cat.h
diff options
context:
space:
mode:
authorGreg Falcon <gfalcon@google.com>2023-06-12 08:25:06 -0700
committerCopybara-Service <copybara-worker@google.com>2023-06-12 08:26:01 -0700
commita3d9a943253f596bd88538f18cc6b07aaba6d3c0 (patch)
tree168cc3be0abfaaf12e646a8279f0183663f7e18a /absl/strings/str_cat.h
parent4500c2fada4e952037c59bd65e8be1ba0b29f21e (diff)
downloadabseil-a3d9a943253f596bd88538f18cc6b07aaba6d3c0.tar.gz
abseil-a3d9a943253f596bd88538f18cc6b07aaba6d3c0.tar.bz2
abseil-a3d9a943253f596bd88538f18cc6b07aaba6d3c0.zip
Fix behaviors of StrCat() and StrFormat() regarding char types and enum types.
This is a conservative change, in that it only contains bugfixes and allows new patterns that used to be compile errors. There are other changes we would like to make (as reflected in the comments in char_formatting_test.cc), but we are being careful about the implications of such behavior changes. The two implementation changes are: * Apply integral promotions to enums before printing them, so they are always treated as integers (and not chars) by StrCat and StrFormat. * Classify `unsigned char` and `signed char` as integer-like rather than char-like, so that `StrFormat("%v", v)` accepts those types as integers (consistent with `StrCat()`.) The behavior changes are: * StrCat() now accepts char-backed enums (rather than failing to compile). * StrFormat("%v") now accepts `signed char` and `unsigned char` as integral (rather than failing to compile). * StrFormat("%v") now correctly formats 8-bit enums as integers (rather than failing internally and emitting nothing). Tested: Modified the char_formatting_test.cc case to reflect changes. Re-ran all other tests. PiperOrigin-RevId: 539659674 Change-Id: Ief56335f5a57e4582af396d00eaa9e7b6be4ddc6
Diffstat (limited to 'absl/strings/str_cat.h')
-rw-r--r--absl/strings/str_cat.h18
1 files changed, 14 insertions, 4 deletions
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h
index fcd48c4e..d5f71ff0 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -374,14 +374,24 @@ class AlphaNum {
const char* data() const { return piece_.data(); }
absl::string_view Piece() const { return piece_; }
- // Normal enums are already handled by the integer formatters.
- // This overload matches only scoped enums.
+ // Match unscoped enums. Use integral promotion so that a `char`-backed
+ // enum becomes a wider integral type AlphaNum will accept.
template <typename T,
typename = typename std::enable_if<
- std::is_enum<T>{} && !std::is_convertible<T, int>{} &&
+ std::is_enum<T>{} && std::is_convertible<T, int>{} &&
!strings_internal::HasAbslStringify<T>::value>::type>
AlphaNum(T e) // NOLINT(runtime/explicit)
- : AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
+ : 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>
+ AlphaNum(T e) // NOLINT(runtime/explicit)
+ : AlphaNum(+static_cast<typename std::underlying_type<T>::type>(e)) {}
// vector<bool>::reference and const_reference require special help to
// convert to `AlphaNum` because it requires two user defined conversions.