Chromium Code Reviews| Index: webrtc/base/optional.h |
| diff --git a/webrtc/base/optional.h b/webrtc/base/optional.h |
| index f5354ee0f25fdb6eabcf6fa367e3db64152681ee..c80d5a4d4eeac633fd01c5732f6531697122d405 100644 |
| --- a/webrtc/base/optional.h |
| +++ b/webrtc/base/optional.h |
| @@ -15,6 +15,11 @@ |
| #include <memory> |
| #include <utility> |
| +#ifdef UNIT_TEST |
|
kwiberg-webrtc
2017/02/18 18:50:47
Who defines this? I couldn't find it in our tree.
kjellander_webrtc
2017/02/19 09:29:19
It comes from gtest: https://cs.chromium.org/chrom
kwiberg-webrtc
2017/02/19 13:14:15
Aha. Excellent!
kjellander_webrtc
2017/02/20 07:24:20
I don't have time to put in more work than this fo
|
| +#include <iomanip> |
| +#include <ostream> |
| +#endif // UNIT_TEST |
| + |
| #include "webrtc/base/array_view.h" |
| #include "webrtc/base/checks.h" |
| #include "webrtc/base/sanitizer.h" |
| @@ -25,7 +30,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 +41,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/18 18:50:47
The outermost const_cast is unnecessary.
ossu
2017/02/20 11:02:24
That is true. But also, I think the whole function
kwiberg-webrtc
2017/02/20 11:45:31
Acknowledged.
|
| +} |
| + |
| #else |
| template <typename T> |
| @@ -296,6 +309,98 @@ class Optional final { |
| }; |
| }; |
| +#ifdef UNIT_TEST |
| +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; |
| +} |
| + |
| +inline void OptionalPrintObjectBytes(const unsigned char* bytes, |
| + size_t size, |
| + std::ostream* os) { |
| + *os << "<optional with " << size << "-byte object ["; |
| + for (size_t i = 0; i != size; ++i) { |
| + *os << (i == 0 ? "" : ((i & 1) ? "-" : " ")); |
| + *os << std::hex << std::setw(2) << std::setfill('0') |
| + << static_cast<int>(bytes[i]); |
| + } |
| + *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>"; |
| + } |
| +} |
| + |
| +#endif // UNIT_TEST |
| + |
| } // namespace rtc |
| #endif // WEBRTC_BASE_OPTIONAL_H_ |