Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1255)

Unified Diff: base/logging.h

Issue 2001783002: base: Support using (D)CHECK on scoped enums. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/logging.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/logging.h
diff --git a/base/logging.h b/base/logging.h
index 0476a4450fb09453db113b38e59b71b5ff226fec..ce1bd4d2e9a3af719a675a628fe861ec3f10d8dc 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -11,6 +11,8 @@
#include <cstring>
#include <sstream>
#include <string>
+#include <type_traits>
+#include <utility>
#include "base/base_export.h"
#include "base/debug/debugger.h"
@@ -519,17 +521,41 @@ class CheckOpResult {
#endif // !(OFFICIAL_BUILD && NDEBUG)
+// Uses expression SFINAE to detect whether using operator<< would work.
+template <typename T, typename = void>
+struct SupportsOstreamOperator : std::false_type {};
danakj 2016/05/20 21:54:16 Can you move this out of logging.h. template_util.
jbroman 2016/05/25 19:08:04 Put it in base::internal since it's internal to ba
+template <typename T>
+struct SupportsOstreamOperator<T,
+ decltype(void(std::declval<std::ostream&>()
jbroman 2016/05/20 19:56:35 "void" here because the type has to match the one
+ << std::declval<T>()))>
+ : std::true_type {};
+
// This formats a value for a failing CHECK_XX statement. Ordinarily,
// it uses the definition for operator<<, with a few special cases below.
+
template <typename T>
-inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
+inline typename std::enable_if<SupportsOstreamOperator<const T&>::value,
+ void>::type
+MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
-// We need an explicit specialization for std::nullptr_t.
-template <>
-BASE_EXPORT void MakeCheckOpValueString(std::ostream* os,
- const std::nullptr_t& p);
+// We need overloads for enums that don't support operator<<.
+// (i.e. scoped enums where no operator<< overload was declared).
+template <typename T>
+inline typename std::enable_if<!SupportsOstreamOperator<const T&>::value &&
danakj 2016/05/20 21:54:16 Random horrible thought: what would go wrong if we
jbroman 2016/05/25 19:08:04 We'd have to change the above condition to !std::i
+ std::is_enum<T>::value,
+ void>::type
+MakeCheckOpValueString(std::ostream* os, const T& v) {
+ // TODO(jbroman): Use std::underlying_type here, once it's available in all
+ // our STL implementations.
+ static_assert(sizeof(T) <= sizeof(int64_t),
jbroman 2016/05/20 19:56:35 64 bits ought to be enough for anybody. :)
+ "enum can't be losslessly printed as int64_t");
+ (*os) << static_cast<int64_t>(v);
dcheng 2016/05/20 19:59:30 What if the enum's underlying type is uint64_t? =)
jbroman 2016/05/20 20:05:38 It'll do the obvious thing (values over 2^63 will
danakj 2016/05/20 21:08:23 Oh, that might actually be nice, I didn't know __u
jbroman 2016/05/25 19:08:04 Done, with the same semi-hacky condition Skia uses
+}
+
+// We need an explicit overload for std::nullptr_t.
+BASE_EXPORT void MakeCheckOpValueString(std::ostream* os, std::nullptr_t p);
// Build the error message string. This is separate from the "Impl"
// function template because it is not performance critical and so can
« no previous file with comments | « no previous file | base/logging.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698