Chromium Code Reviews| Index: base/logging.h |
| diff --git a/base/logging.h b/base/logging.h |
| index 8c7f20ad193eb1a6f7f398d74788e0fd95c45546..3e7477f4f5166ce1998cb529c63b9266a482654d 100644 |
| --- a/base/logging.h |
| +++ b/base/logging.h |
| @@ -9,6 +9,7 @@ |
| #include <string> |
| #include <cstring> |
| #include <sstream> |
| +#include <type_traits> |
|
dcheng
2015/11/13 03:30:23
Pretty sure this isn't allowed yet.
|
| #include "base/base_export.h" |
| #include "base/basictypes.h" |
| @@ -513,18 +514,45 @@ class CheckOpResult { |
| #endif |
| +namespace internal { |
| +// Type trait helper to detect scoped enums. |
| +template <typename T> |
| +using is_scoped_enum = |
| + std::integral_constant<bool, |
| + std::is_enum<T>::value && |
| + !std::is_convertible<T, int>::value>; |
| +} // namespace internal |
| + |
| // Build the error message string. This is separate from the "Impl" |
| // function template because it is not performance critical and so can |
| // be out of line, while the "Impl" code should be inline. Caller |
| // takes ownership of the returned string. |
| -template<class t1, class t2> |
| -std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { |
| +template <class T1, |
| + class T2, |
| + typename std::enable_if<!internal::is_scoped_enum<T1>::value && |
| + !internal::is_scoped_enum<T2>::value>::type* = |
| + nullptr> |
| +std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* names) { |
| std::ostringstream ss; |
| ss << names << " (" << v1 << " vs. " << v2 << ")"; |
| std::string* msg = new std::string(ss.str()); |
| return msg; |
| } |
| +// Template specialization for scoped enums. Only allows comparisons between |
| +// values from the same scoped enum. |
| +template <class T, |
| + typename std::enable_if<internal::is_scoped_enum<T>::value>::type* = |
| + nullptr> |
| +std::string* MakeCheckOpString(const T& v1, const T& v2, const char* names) { |
| + using EnumIntegralType = typename std::underlying_type<T>::type; |
| + std::ostringstream ss; |
| + ss << names << " (" << static_cast<EnumIntegralType>(v1) << " vs. " |
| + << static_cast<EnumIntegralType>(v2) << ")"; |
| + std::string* msg = new std::string(ss.str()); |
| + return msg; |
| +} |
| + |
| // Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated |
| // in logging.cc. |
| extern template BASE_EXPORT std::string* MakeCheckOpString<int, int>( |