Revert "libchrome: Remove first-use-of-C++-20 patch"

This reverts commit 5c5565f9adb3bfadfd54392c003815eac5aa6fe8.

Reason for revert: breaking packages in the CQ; b/307977920

Original change's description:
> libchrome: Remove first-use-of-C++-20 patch
>
> Removing this patch will reintroduce real uses of C++20-only features
> into base/. The previous attempt to do this (crrev.com/c/4929179)
> uncovered some non-C++20-ready projects which have since been fixed.
>
> BUG=b:294233104
> TEST=CQ
>
> Cq-Depend: chromium:4975281
> Change-Id: I793aa22c6fb98cd23fd2b792dcb2af63221d37f2
> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/libchrome/+/4975080
> Tested-by: Andrew Moylan <amoylan@chromium.org>
> Commit-Queue: Andrew Moylan <amoylan@chromium.org>
> Reviewed-by: Grace Cham <hscham@chromium.org>

BUG=b:294233104, b:307977920

Change-Id: I357779a295aa8176f535e109725952c5a6ac7d8d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/libchrome/+/4981387
Owners-Override: Aaron Massey <aaronmassey@google.com>
Reviewed-by: Aaron Massey <aaronmassey@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Tested-by: Aaron Massey <aaronmassey@google.com>
Auto-Submit: George Burgess <gbiv@chromium.org>
Tested-by: George Burgess <gbiv@chromium.org>
diff --git a/libchrome_tools/patches/backward-compatibility-1400-Revert-Land-intentional-C-20-use-in-base.patch b/libchrome_tools/patches/backward-compatibility-1400-Revert-Land-intentional-C-20-use-in-base.patch
new file mode 100644
index 0000000..52be7cc
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1400-Revert-Land-intentional-C-20-use-in-base.patch
@@ -0,0 +1,292 @@
+From 62bba06a487ff8ec300847d916705cddfdbc2719 Mon Sep 17 00:00:00 2001
+From: Nathan Muggli <nmuggli@google.com>
+Date: Wed, 2 Aug 2023 10:26:12 -0600
+Subject: [PATCH] Revert "Land intentional C++20 use in base/."
+
+This reverts commit c5acc58e7bebe5de213668909a9414b97c58c9c7.
+
+patch-name: backward-compatibility-1400-Revert-Land-intentional-C-20-use-in-base.patch
+Change-Id: Iab4e3adeb005025fdecdfeef6786662692aa11c0
+---
+ base/check_op.h                               |  9 +++--
+ base/strings/to_string.h                      | 34 +++++++++-------
+ base/strings/to_string_unittest.cc            | 16 ++------
+ base/types/strong_alias.h                     |  2 +-
+ base/types/strong_alias_unittest.cc           |  4 +-
+ base/types/supports_ostream_operator.h        | 10 +++--
+ .../supports_ostream_operator_unittest.cc     | 39 ++++++++++---------
+ 7 files changed, 61 insertions(+), 53 deletions(-)
+
+diff --git a/base/check_op.h b/base/check_op.h
+index 53eb17b67b..d4e3bf7f6d 100644
+--- a/base/check_op.h
++++ b/base/check_op.h
+@@ -70,7 +70,7 @@ BASE_EXPORT char* StreamValToStr(const void* v,
+ 
+ template <typename T>
+ inline typename std::enable_if<
+-    base::internal::SupportsOstreamOperator<const T&> &&
++    base::internal::SupportsOstreamOperator<const T&>::value &&
+         !std::is_function_v<typename std::remove_pointer<T>::type>,
+     char*>::type
+ CheckOpValueStr(const T& v) {
+@@ -96,8 +96,8 @@ CheckOpValueStr(const T& v) {
+ // Overload for types that have no operator<< but do have .ToString() defined.
+ template <typename T>
+ inline typename std::enable_if<
+-    !base::internal::SupportsOstreamOperator<const T&> &&
+-        base::internal::SupportsToString<const T&>,
++    !base::internal::SupportsOstreamOperator<const T&>::value &&
++        base::internal::SupportsToString<const T&>::value,
+     char*>::type
+ CheckOpValueStr(const T& v) {
+   // .ToString() may not return a std::string, e.g. blink::WTF::String.
+@@ -121,7 +121,8 @@ CheckOpValueStr(const T& v) {
+ // (i.e. scoped enums where no operator<< overload was declared).
+ template <typename T>
+ inline typename std::enable_if<
+-    !base::internal::SupportsOstreamOperator<const T&> && std::is_enum_v<T>,
++    !base::internal::SupportsOstreamOperator<const T&>::value &&
++        std::is_enum_v<T>,
+     char*>::type
+ CheckOpValueStr(const T& v) {
+   return CheckOpValueStr(
+diff --git a/base/strings/to_string.h b/base/strings/to_string.h
+index eae7b944cd..911622db47 100644
+--- a/base/strings/to_string.h
++++ b/base/strings/to_string.h
+@@ -23,8 +23,11 @@ std::string ToString(const Ts&... values);
+ 
+ namespace internal {
+ 
++template <typename T, typename = void>
++struct SupportsToString : std::false_type {};
+ template <typename T>
+-concept SupportsToString = requires(const T& t) { t.ToString(); };
++struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))>
++    : std::true_type {};
+ 
+ // I/O manipulators are function pointers, but should be sent directly to the
+ // `ostream` instead of being cast to `const void*` like other function
+@@ -56,17 +59,19 @@ struct ToStringHelper {
+ 
+ // Most streamables.
+ template <typename T>
+-struct ToStringHelper<T,
+-                      std::enable_if_t<SupportsOstreamOperator<const T&> &&
+-                                       !WillBeIncorrectlyStreamedAsBool<T>>> {
++struct ToStringHelper<
++    T,
++    std::enable_if_t<SupportsOstreamOperator<const T&>::value &&
++                     !WillBeIncorrectlyStreamedAsBool<T>>> {
+   static void Stringify(const T& v, std::ostringstream& ss) { ss << v; }
+ };
+ 
+ // Functions and function pointers.
+ template <typename T>
+-struct ToStringHelper<T,
+-                      std::enable_if_t<SupportsOstreamOperator<const T&> &&
+-                                       WillBeIncorrectlyStreamedAsBool<T>>> {
++struct ToStringHelper<
++    T,
++    std::enable_if_t<SupportsOstreamOperator<const T&>::value &&
++                     WillBeIncorrectlyStreamedAsBool<T>>> {
+   static void Stringify(const T& v, std::ostringstream& ss) {
+     ToStringHelper<const void*>::Stringify(reinterpret_cast<const void*>(v),
+                                            ss);
+@@ -75,9 +80,10 @@ struct ToStringHelper<T,
+ 
+ // Non-streamables that have a `ToString` member.
+ template <typename T>
+-struct ToStringHelper<T,
+-                      std::enable_if_t<!SupportsOstreamOperator<const T&> &&
+-                                       SupportsToString<const T&>>> {
++struct ToStringHelper<
++    T,
++    std::enable_if_t<!SupportsOstreamOperator<const T&>::value &&
++                     SupportsToString<const T&>::value>> {
+   static void Stringify(const T& v, std::ostringstream& ss) {
+     // .ToString() may not return a std::string, e.g. blink::WTF::String.
+     ToStringHelper<decltype(v.ToString())>::Stringify(v.ToString(), ss);
+@@ -89,7 +95,8 @@ struct ToStringHelper<T,
+ template <typename T>
+ struct ToStringHelper<
+     T,
+-    std::enable_if_t<!SupportsOstreamOperator<const T&> && std::is_enum_v<T>>> {
++    std::enable_if_t<!SupportsOstreamOperator<const T&>::value &&
++                     std::is_enum_v<T>>> {
+   static void Stringify(const T& v, std::ostringstream& ss) {
+     using UT = typename std::underlying_type_t<T>;
+     ToStringHelper<UT>::Stringify(static_cast<UT>(v), ss);
+@@ -120,8 +127,9 @@ struct ToStringHelper<std::tuple<T...>> {
+ template <typename... Ts>
+ std::string ToString(const Ts&... values) {
+   std::ostringstream ss;
+-  (..., internal::ToStringHelper<remove_cvref_t<decltype(values)>>::Stringify(
+-            values, ss));
++  (internal::ToStringHelper<remove_cvref_t<decltype(values)>>::Stringify(values,
++                                                                         ss),
++   ...);
+   return ss.str();
+ }
+ 
+diff --git a/base/strings/to_string_unittest.cc b/base/strings/to_string_unittest.cc
+index dca285ff52..3cb3c22356 100644
+--- a/base/strings/to_string_unittest.cc
++++ b/base/strings/to_string_unittest.cc
+@@ -20,22 +20,14 @@ class HasToString {
+ };
+ 
+ // .ToString() support on structs.
+-static_assert(!internal::SupportsToString<NotStringifiable>,
++static_assert(!internal::SupportsToString<NotStringifiable>::value,
+               "value without ToString() shouldn't be marked SupportsToString");
+-static_assert(!internal::SupportsToString<NotStringifiable&>,
+-              "& without ToString() shouldn't be marked SupportsToString");
+-static_assert(!internal::SupportsToString<const NotStringifiable&>,
++static_assert(!internal::SupportsToString<const NotStringifiable&>::value,
+               "const& without ToString() shouldn't be marked SupportsToString");
+-static_assert(!internal::SupportsToString<NotStringifiable&&>,
+-              "&& without ToString() shouldn't be marked SupportsToString");
+-static_assert(internal::SupportsToString<HasToString>,
++static_assert(internal::SupportsToString<HasToString>::value,
+               "value with ToString() should be marked SupportsToString");
+-static_assert(internal::SupportsToString<HasToString&>,
+-              "& with ToString() should be marked SupportsToString");
+-static_assert(internal::SupportsToString<const HasToString&>,
++static_assert(internal::SupportsToString<const HasToString&>::value,
+               "const& with ToString() should be marked SupportsToString");
+-static_assert(internal::SupportsToString<HasToString&&>,
+-              "&& with ToString() should be marked SupportsToString");
+ 
+ TEST(ToStringTest, Streamable) {
+   // Types with built-in <<.
+diff --git a/base/types/strong_alias.h b/base/types/strong_alias.h
+index 79d39808b0..7a4872a4a0 100644
+--- a/base/types/strong_alias.h
++++ b/base/types/strong_alias.h
+@@ -154,7 +154,7 @@ class StrongAlias {
+ template <typename TagType,
+           typename UnderlyingType,
+           typename = std::enable_if_t<
+-              internal::SupportsOstreamOperator<UnderlyingType>>>
++              internal::SupportsOstreamOperator<UnderlyingType>::value>>
+ std::ostream& operator<<(std::ostream& stream,
+                          const StrongAlias<TagType, UnderlyingType>& alias) {
+   return stream << alias.value();
+diff --git a/base/types/strong_alias_unittest.cc b/base/types/strong_alias_unittest.cc
+index e69cf7b704..b211d3b474 100644
+--- a/base/types/strong_alias_unittest.cc
++++ b/base/types/strong_alias_unittest.cc
+@@ -371,7 +371,7 @@ TEST(StrongAliasTest, EnsureConstexpr) {
+ void StreamOperatorExists() {
+   // Aliases of ints should be streamable because ints are streamable.
+   using StreamableAlias = StrongAlias<class IntTag, int>;
+-  static_assert(internal::SupportsOstreamOperator<StreamableAlias>);
++  static_assert(internal::SupportsOstreamOperator<StreamableAlias>::value);
+ 
+   // Aliases of a class which does not expose a stream operator should
+   // themselves not be streamable.
+@@ -380,7 +380,7 @@ void StreamOperatorExists() {
+     Scope() = default;
+   };
+   using NonStreamableAlias = StrongAlias<class ScopeTag, Scope>;
+-  static_assert(!internal::SupportsOstreamOperator<NonStreamableAlias>);
++  static_assert(!internal::SupportsOstreamOperator<NonStreamableAlias>::value);
+ }
+ 
+ #if BUILDFLAG(ENABLE_BASE_TRACING)
+diff --git a/base/types/supports_ostream_operator.h b/base/types/supports_ostream_operator.h
+index 7e0100f970..0803db4862 100644
+--- a/base/types/supports_ostream_operator.h
++++ b/base/types/supports_ostream_operator.h
+@@ -11,13 +11,17 @@
+ 
+ namespace base::internal {
+ 
+-// Detects whether using operator<< would work.
++// Uses expression SFINAE to detect whether using operator<< would work.
+ //
+ // Note that the above #include of <ostream> is necessary to guarantee
+ // consistent results here for basic types.
++template <typename T, typename = void>
++struct SupportsOstreamOperator : std::false_type {};
+ template <typename T>
+-concept SupportsOstreamOperator =
+-    requires(const T& t, std::ostream& os) { os << t; };
++struct SupportsOstreamOperator<T,
++                               decltype(void(std::declval<std::ostream&>()
++                                             << std::declval<T>()))>
++    : std::true_type {};
+ 
+ }  // namespace base::internal
+ 
+diff --git a/base/types/supports_ostream_operator_unittest.cc b/base/types/supports_ostream_operator_unittest.cc
+index 31e2628962..0f8c3a09d9 100644
+--- a/base/types/supports_ostream_operator_unittest.cc
++++ b/base/types/supports_ostream_operator_unittest.cc
+@@ -26,40 +26,43 @@ std::ostream& operator<<(std::ostream& os, const StructWithOperator& v) {
+ }
+ 
+ // A few standard types that definitely support printing.
+-static_assert(internal::SupportsOstreamOperator<int>,
++static_assert(internal::SupportsOstreamOperator<int>::value,
+               "ints should be printable");
+-static_assert(internal::SupportsOstreamOperator<const char*>,
++static_assert(internal::SupportsOstreamOperator<const char*>::value,
+               "C strings should be printable");
+-static_assert(internal::SupportsOstreamOperator<std::string>,
++static_assert(internal::SupportsOstreamOperator<std::string>::value,
+               "std::string should be printable");
+ 
+ // Various kinds of enums operator<< support.
+-static_assert(internal::SupportsOstreamOperator<SimpleEnum>,
++static_assert(internal::SupportsOstreamOperator<SimpleEnum>::value,
+               "simple enum should be printable by value");
+-static_assert(internal::SupportsOstreamOperator<const SimpleEnum&>,
++static_assert(internal::SupportsOstreamOperator<const SimpleEnum&>::value,
+               "simple enum should be printable by const ref");
+-static_assert(internal::SupportsOstreamOperator<EnumWithExplicitType>,
++static_assert(internal::SupportsOstreamOperator<EnumWithExplicitType>::value,
+               "enum with explicit type should be printable by value");
+-static_assert(internal::SupportsOstreamOperator<const EnumWithExplicitType&>,
+-              "enum with explicit type should be printable by const ref");
+-static_assert(!internal::SupportsOstreamOperator<ScopedEnum>,
++static_assert(
++    internal::SupportsOstreamOperator<const EnumWithExplicitType&>::value,
++    "enum with explicit type should be printable by const ref");
++static_assert(!internal::SupportsOstreamOperator<ScopedEnum>::value,
+               "scoped enum should not be printable by value");
+-static_assert(!internal::SupportsOstreamOperator<const ScopedEnum&>,
++static_assert(!internal::SupportsOstreamOperator<const ScopedEnum&>::value,
+               "simple enum should not be printable by const ref");
+-static_assert(internal::SupportsOstreamOperator<ScopedEnumWithOperator>,
++static_assert(internal::SupportsOstreamOperator<ScopedEnumWithOperator>::value,
+               "scoped enum with operator<< should be printable by value");
+-static_assert(internal::SupportsOstreamOperator<const ScopedEnumWithOperator&>,
+-              "scoped enum with operator<< should be printable by const ref");
++static_assert(
++    internal::SupportsOstreamOperator<const ScopedEnumWithOperator&>::value,
++    "scoped enum with operator<< should be printable by const ref");
+ 
+ // operator<< support on structs.
+-static_assert(!internal::SupportsOstreamOperator<SimpleStruct>,
++static_assert(!internal::SupportsOstreamOperator<SimpleStruct>::value,
+               "simple struct should not be printable by value");
+-static_assert(!internal::SupportsOstreamOperator<const SimpleStruct&>,
++static_assert(!internal::SupportsOstreamOperator<const SimpleStruct&>::value,
+               "simple struct should not be printable by const ref");
+-static_assert(internal::SupportsOstreamOperator<StructWithOperator>,
++static_assert(internal::SupportsOstreamOperator<StructWithOperator>::value,
+               "struct with operator<< should be printable by value");
+-static_assert(internal::SupportsOstreamOperator<const StructWithOperator&>,
+-              "struct with operator<< should be printable by const ref");
++static_assert(
++    internal::SupportsOstreamOperator<const StructWithOperator&>::value,
++    "struct with operator<< should be printable by const ref");
+ 
+ }  // namespace
+ }  // namespace base
+-- 
+2.42.0.758.gaed0368e0e-goog
+