Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_OPTIONAL_H_ | 5 #ifndef BASE_OPTIONAL_H_ |
| 6 #define BASE_OPTIONAL_H_ | 6 #define BASE_OPTIONAL_H_ |
| 7 | 7 |
| 8 #include <type_traits> | 8 #include <type_traits> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 constexpr in_place_t in_place = {}; | 27 constexpr in_place_t in_place = {}; |
| 28 | 28 |
| 29 // Specification: | 29 // Specification: |
| 30 // http://en.cppreference.com/w/cpp/utility/optional/nullopt | 30 // http://en.cppreference.com/w/cpp/utility/optional/nullopt |
| 31 constexpr nullopt_t nullopt(0); | 31 constexpr nullopt_t nullopt(0); |
| 32 | 32 |
| 33 namespace internal { | 33 namespace internal { |
| 34 | 34 |
| 35 template <typename T, bool = base::is_trivially_destructible<T>::value> | 35 template <typename T, bool = base::is_trivially_destructible<T>::value> |
| 36 struct OptionalStorage { | 36 struct OptionalStorage { |
| 37 constexpr OptionalStorage() {} | 37 // Initializing |empty_| here to avoid errors in g++ 4.8. |
| 38 constexpr OptionalStorage() : empty_('\0') {} | |
| 38 | 39 |
| 39 constexpr explicit OptionalStorage(const T& value) | 40 constexpr explicit OptionalStorage(const T& value) |
| 40 : is_null_(false), value_(value) {} | 41 : is_null_(false), value_(value) {} |
| 41 | 42 |
| 42 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. | 43 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
| 43 explicit OptionalStorage(T&& value) | 44 explicit OptionalStorage(T&& value) |
| 44 : is_null_(false), value_(std::move(value)) {} | 45 : is_null_(false), value_(std::move(value)) {} |
| 45 | 46 |
| 46 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. | 47 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
| 47 template <class... Args> | 48 template <class... Args> |
| 48 explicit OptionalStorage(base::in_place_t, Args&&... args) | 49 explicit OptionalStorage(base::in_place_t, Args&&... args) |
| 49 : is_null_(false), value_(std::forward<Args>(args)...) {} | 50 : is_null_(false), value_(std::forward<Args>(args)...) {} |
| 50 | 51 |
| 51 // When T is not trivially destructible we must call its | 52 // When T is not trivially destructible we must call its |
| 52 // destructor before deallocating its memory. | 53 // destructor before deallocating its memory. |
| 53 ~OptionalStorage() { | 54 ~OptionalStorage() { |
| 54 if (!is_null_) | 55 if (!is_null_) |
| 55 value_.~T(); | 56 value_.~T(); |
| 56 } | 57 } |
| 57 | 58 |
| 58 bool is_null_ = true; | 59 bool is_null_ = true; |
| 59 union { | 60 union { |
| 60 // |empty_| exists so that the union will always be initialized, even when | 61 // |empty_| exists so that the union will always be initialized, even when |
| 61 // it doesn't contain a value. Not initializing it has been observed to | 62 // it doesn't contain a value. Not initializing it has been observed to |
| 62 // trigger comiler warnings. | 63 // trigger comiler warnings. |
| 63 char empty_ = '\0'; | 64 char empty_ = '\0'; |
|
danakj
2016/10/26 18:56:49
can you drop the \0 here then cuz it's redundant
alshabalin
2016/10/26 20:42:38
Done.
| |
| 64 T value_; | 65 T value_; |
| 65 }; | 66 }; |
| 66 }; | 67 }; |
| 67 | 68 |
| 68 template <typename T> | 69 template <typename T> |
| 69 struct OptionalStorage<T, true> { | 70 struct OptionalStorage<T, true> { |
| 70 constexpr OptionalStorage() {} | 71 // Initializing |empty_| here to avoid errors in g++ 4.8. |
| 72 constexpr OptionalStorage() : empty_('\0') {} | |
| 71 | 73 |
| 72 constexpr explicit OptionalStorage(const T& value) | 74 constexpr explicit OptionalStorage(const T& value) |
| 73 : is_null_(false), value_(value) {} | 75 : is_null_(false), value_(value) {} |
| 74 | 76 |
| 75 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. | 77 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
| 76 explicit OptionalStorage(T&& value) | 78 explicit OptionalStorage(T&& value) |
| 77 : is_null_(false), value_(std::move(value)) {} | 79 : is_null_(false), value_(std::move(value)) {} |
| 78 | 80 |
| 79 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. | 81 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
| 80 template <class... Args> | 82 template <class... Args> |
| 81 explicit OptionalStorage(base::in_place_t, Args&&... args) | 83 explicit OptionalStorage(base::in_place_t, Args&&... args) |
| 82 : is_null_(false), value_(std::forward<Args>(args)...) {} | 84 : is_null_(false), value_(std::forward<Args>(args)...) {} |
| 83 | 85 |
| 84 // When T is trivially destructible (i.e. its destructor does nothing) there | 86 // When T is trivially destructible (i.e. its destructor does nothing) there |
| 85 // is no need to call it. Explicitly defaulting the destructor means it's not | 87 // is no need to call it. Explicitly defaulting the destructor means it's not |
| 86 // user-provided. Those two together make this destructor trivial. | 88 // user-provided. Those two together make this destructor trivial. |
| 87 ~OptionalStorage() = default; | 89 ~OptionalStorage() = default; |
| 88 | 90 |
| 89 bool is_null_ = true; | 91 bool is_null_ = true; |
| 90 union { | 92 union { |
| 91 // |empty_| exists so that the union will always be initialized, even when | 93 // |empty_| exists so that the union will always be initialized, even when |
| 92 // it doesn't contain a value. Not initializing it has been observed to | 94 // it doesn't contain a value. Not initializing it has been observed to |
| 93 // trigger comiler warnings. | 95 // trigger comiler warnings. |
| 94 char empty_ = '\0'; | 96 char empty_ = '\0'; |
|
danakj
2016/10/26 18:56:49
same
alshabalin
2016/10/26 20:42:38
Done.
| |
| 95 T value_; | 97 T value_; |
| 96 }; | 98 }; |
| 97 }; | 99 }; |
| 98 | 100 |
| 99 } // namespace internal | 101 } // namespace internal |
| 100 | 102 |
| 101 // base::Optional is a Chromium version of the C++17 optional class: | 103 // base::Optional is a Chromium version of the C++17 optional class: |
| 102 // std::optional documentation: | 104 // std::optional documentation: |
| 103 // http://en.cppreference.com/w/cpp/utility/optional | 105 // http://en.cppreference.com/w/cpp/utility/optional |
| 104 // Chromium documentation: | 106 // Chromium documentation: |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 template <class T> | 495 template <class T> |
| 494 struct hash<base::Optional<T>> { | 496 struct hash<base::Optional<T>> { |
| 495 size_t operator()(const base::Optional<T>& opt) const { | 497 size_t operator()(const base::Optional<T>& opt) const { |
| 496 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); | 498 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); |
| 497 } | 499 } |
| 498 }; | 500 }; |
| 499 | 501 |
| 500 } // namespace std | 502 } // namespace std |
| 501 | 503 |
| 502 #endif // BASE_OPTIONAL_H_ | 504 #endif // BASE_OPTIONAL_H_ |
| OLD | NEW |