OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_BASE_OPTIONAL_H_ | 11 #ifndef WEBRTC_BASE_OPTIONAL_H_ |
12 #define WEBRTC_BASE_OPTIONAL_H_ | 12 #define WEBRTC_BASE_OPTIONAL_H_ |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <memory> | 15 #include <memory> |
16 #include <ostream> | |
16 #include <utility> | 17 #include <utility> |
17 | 18 |
18 #include "webrtc/base/array_view.h" | 19 #include "webrtc/base/array_view.h" |
19 #include "webrtc/base/checks.h" | 20 #include "webrtc/base/checks.h" |
20 #include "webrtc/base/sanitizer.h" | 21 #include "webrtc/base/sanitizer.h" |
21 | 22 |
22 namespace rtc { | 23 namespace rtc { |
23 | 24 |
24 namespace optional_internal { | 25 namespace optional_internal { |
25 | 26 |
26 #if RTC_HAS_ASAN | 27 #if RTC_HAS_ASAN |
27 | 28 |
28 // This is a non-inlined function. The optimizer can't see inside it. | 29 // This is a non-inlined function. The optimizer can't see inside it. It |
30 // prevents the compiler from generating optimized code that reads value_ even | |
31 // if it is unset. Although safe, this causes memory sanitizers to complain. | |
29 void* FunctionThatDoesNothingImpl(void*); | 32 void* FunctionThatDoesNothingImpl(void*); |
30 | 33 |
31 template <typename T> | 34 template <typename T> |
32 inline T* FunctionThatDoesNothing(T* x) { | 35 inline T* FunctionThatDoesNothing(T* x) { |
33 return reinterpret_cast<T*>( | 36 return reinterpret_cast<T*>( |
34 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x))); | 37 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x))); |
35 } | 38 } |
36 | 39 |
40 template <typename T> | |
41 inline const T* FunctionThatDoesNothing(const T* x) { | |
42 return const_cast<const T*>(reinterpret_cast<T*>( | |
43 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(const_cast<T*>(x))))); | |
44 } | |
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
| |
45 | |
37 #else | 46 #else |
38 | 47 |
39 template <typename T> | 48 template <typename T> |
40 inline T* FunctionThatDoesNothing(T* x) { return x; } | 49 inline T* FunctionThatDoesNothing(T* x) { return x; } |
41 | 50 |
42 #endif | 51 #endif |
43 | 52 |
44 } // namespace optional_internal | 53 } // namespace optional_internal |
45 | 54 |
46 // Simple std::optional-wannabe. It either contains a T or not. | 55 // Simple std::optional-wannabe. It either contains a T or not. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 char empty_; | 298 char empty_; |
290 // By placing value_ in a union, we get to manage its construction and | 299 // By placing value_ in a union, we get to manage its construction and |
291 // destruction manually: the Optional constructors won't automatically | 300 // destruction manually: the Optional constructors won't automatically |
292 // construct it, and the Optional destructor won't automatically destroy | 301 // construct it, and the Optional destructor won't automatically destroy |
293 // it. Basically, this just allocates a properly sized and aligned block of | 302 // it. Basically, this just allocates a properly sized and aligned block of |
294 // memory in which we can manually put a T with placement new. | 303 // memory in which we can manually put a T with placement new. |
295 T value_; | 304 T value_; |
296 }; | 305 }; |
297 }; | 306 }; |
298 | 307 |
308 namespace optional_internal { | |
309 | |
310 // Checks if there's a valid PrintTo(const T&, std::ostream*) call for T. | |
311 template <typename T> | |
312 struct HasPrintTo { | |
313 private: | |
314 struct No {}; | |
315 | |
316 template <typename T2> | |
317 static auto Test(const T2& obj) | |
318 -> decltype(PrintTo(obj, std::declval<std::ostream*>())); | |
319 | |
320 template <typename> | |
321 static No Test(...); | |
322 | |
323 public: | |
324 static constexpr bool value = | |
325 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value; | |
326 }; | |
327 | |
328 // Checks if there's a valid operator<<(std::ostream&, const T&) call for T. | |
329 template <typename T> | |
330 struct HasOstreamOperator { | |
331 private: | |
332 struct No {}; | |
333 | |
334 template <typename T2> | |
335 static auto Test(const T2& obj) | |
336 -> decltype(std::declval<std::ostream&>() << obj); | |
337 | |
338 template <typename> | |
339 static No Test(...); | |
340 | |
341 public: | |
342 static constexpr bool value = | |
343 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value; | |
344 }; | |
345 | |
346 // Prefer using PrintTo to print the object. | |
347 template <typename T> | |
348 typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper( | |
349 const T& value, | |
350 std::ostream* os) { | |
351 PrintTo(value, os); | |
352 } | |
353 | |
354 // Fall back to operator<<(std::ostream&, ...) if it exists. | |
355 template <typename T> | |
356 typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value, | |
357 void>::type | |
358 OptionalPrintToHelper(const T& value, std::ostream* os) { | |
359 *os << value; | |
360 } | |
361 | |
362 void OptionalPrintObjectBytes(const unsigned char* bytes, | |
363 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
| |
364 std::ostream* os); | |
365 | |
366 // As a final back-up, just print the contents of the objcets byte-wise. | |
367 template <typename T> | |
368 typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value, | |
369 void>::type | |
370 OptionalPrintToHelper(const T& value, std::ostream* os) { | |
371 OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value), | |
372 sizeof(value), os); | |
373 } | |
374 | |
375 } // namespace optional_internal | |
376 | |
377 // PrintTo is used by gtest to print out the results of tests. We want to ensure | |
378 // the object contained in an Optional can be printed out if it's set, while | |
379 // avoiding touching the object's storage if it is undefined. | |
380 template <typename T> | |
381 void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) { | |
382 if (opt) { | |
383 optional_internal::OptionalPrintToHelper(*opt, os); | |
384 } else { | |
385 *os << "<empty optional>"; | |
386 } | |
387 } | |
388 | |
299 } // namespace rtc | 389 } // namespace rtc |
300 | 390 |
301 #endif // WEBRTC_BASE_OPTIONAL_H_ | 391 #endif // WEBRTC_BASE_OPTIONAL_H_ |
OLD | NEW |