Chromium Code Reviews| Index: webrtc/base/optional.h | 
| diff --git a/webrtc/base/optional.h b/webrtc/base/optional.h | 
| index f5354ee0f25fdb6eabcf6fa367e3db64152681ee..ecc0c0be3cda9392276f41e14dbd76bc8ade3da2 100644 | 
| --- a/webrtc/base/optional.h | 
| +++ b/webrtc/base/optional.h | 
| @@ -13,6 +13,7 @@ | 
| #include <algorithm> | 
| #include <memory> | 
| +#include <ostream> | 
| #include <utility> | 
| #include "webrtc/base/array_view.h" | 
| @@ -25,7 +26,9 @@ namespace optional_internal { | 
| #if RTC_HAS_ASAN | 
| -// This is a non-inlined function. The optimizer can't see inside it. | 
| +// This is a non-inlined function. The optimizer can't see inside it. It | 
| +// prevents the compiler from generating optimized code that reads value_ even | 
| +// if it is unset. Although safe, this causes memory sanitizers to complain. | 
| void* FunctionThatDoesNothingImpl(void*); | 
| template <typename T> | 
| @@ -34,6 +37,12 @@ inline T* FunctionThatDoesNothing(T* x) { | 
| FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x))); | 
| } | 
| +template <typename T> | 
| +inline const T* FunctionThatDoesNothing(const T* x) { | 
| + return const_cast<const T*>(reinterpret_cast<T*>( | 
| + FunctionThatDoesNothingImpl(reinterpret_cast<void*>(const_cast<T*>(x))))); | 
| +} | 
| 
 
kwiberg-webrtc
2017/02/17 13:50:17
Hmm. Wouldn't it be more general to just have one
 
ossu
2017/02/17 14:02:19
Nope, the problem was that the compiler disallowed
 
 | 
| + | 
| #else | 
| template <typename T> | 
| @@ -296,6 +305,87 @@ class Optional final { | 
| }; | 
| }; | 
| +namespace optional_internal { | 
| + | 
| +// Checks if there's a valid PrintTo(const T&, std::ostream*) call for T. | 
| +template <typename T> | 
| +struct HasPrintTo { | 
| + private: | 
| + struct No {}; | 
| + | 
| + template <typename T2> | 
| + static auto Test(const T2& obj) | 
| + -> decltype(PrintTo(obj, std::declval<std::ostream*>())); | 
| + | 
| + template <typename> | 
| + static No Test(...); | 
| + | 
| + public: | 
| + static constexpr bool value = | 
| + !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value; | 
| +}; | 
| + | 
| +// Checks if there's a valid operator<<(std::ostream&, const T&) call for T. | 
| +template <typename T> | 
| +struct HasOstreamOperator { | 
| + private: | 
| + struct No {}; | 
| + | 
| + template <typename T2> | 
| + static auto Test(const T2& obj) | 
| + -> decltype(std::declval<std::ostream&>() << obj); | 
| + | 
| + template <typename> | 
| + static No Test(...); | 
| + | 
| + public: | 
| + static constexpr bool value = | 
| + !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value; | 
| +}; | 
| + | 
| +// Prefer using PrintTo to print the object. | 
| +template <typename T> | 
| +typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper( | 
| + const T& value, | 
| + std::ostream* os) { | 
| + PrintTo(value, os); | 
| +} | 
| + | 
| +// Fall back to operator<<(std::ostream&, ...) if it exists. | 
| +template <typename T> | 
| +typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value, | 
| + void>::type | 
| +OptionalPrintToHelper(const T& value, std::ostream* os) { | 
| + *os << value; | 
| +} | 
| + | 
| +void OptionalPrintObjectBytes(const unsigned char* bytes, | 
| + size_t size, | 
| 
 
kwiberg-webrtc
2017/02/17 13:50:17
ArrayView?
 
ossu
2017/02/17 14:02:20
Not certain the extra dependency is worth it, hone
 
 | 
| + std::ostream* os); | 
| + | 
| +// As a final back-up, just print the contents of the objcets byte-wise. | 
| +template <typename T> | 
| +typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value, | 
| + void>::type | 
| +OptionalPrintToHelper(const T& value, std::ostream* os) { | 
| + OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value), | 
| + sizeof(value), os); | 
| +} | 
| + | 
| +} // namespace optional_internal | 
| + | 
| +// PrintTo is used by gtest to print out the results of tests. We want to ensure | 
| +// the object contained in an Optional can be printed out if it's set, while | 
| +// avoiding touching the object's storage if it is undefined. | 
| +template <typename T> | 
| +void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) { | 
| + if (opt) { | 
| + optional_internal::OptionalPrintToHelper(*opt, os); | 
| + } else { | 
| + *os << "<empty optional>"; | 
| + } | 
| +} | 
| + | 
| } // namespace rtc | 
| #endif // WEBRTC_BASE_OPTIONAL_H_ |