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 OptionalStorage() {} | 37 constexpr OptionalStorage() {} |
38 constexpr explicit OptionalStorage(const T& value) | |
39 : is_null_(false), value_(value) {} | |
40 constexpr explicit OptionalStorage(T&& value) | |
41 : is_null_(false), value_(std::move(value)) {} | |
42 template <class... Args> | |
43 constexpr explicit OptionalStorage(base::in_place_t, Args&&... args) | |
44 : is_null_(false), value_(std::forward<Args>(args)...) {} | |
38 // When T is not trivially destructible we must call its | 45 // When T is not trivially destructible we must call its |
danakj
2016/10/21 23:12:08
nit: whitespace above this to separate it since we
alshabalin
2016/10/22 07:47:52
Done.
| |
39 // destructor before deallocating its memory. | 46 // destructor before deallocating its memory. |
40 ~OptionalStorage() { | 47 ~OptionalStorage() { |
41 if (!is_null_) | 48 if (!is_null_) |
42 value_.~T(); | 49 value_.~T(); |
43 } | 50 } |
44 | 51 |
45 bool is_null_ = true; | 52 bool is_null_ = true; |
46 union { | 53 union { |
47 // |empty_| exists so that the union will always be initialized, even when | 54 // |empty_| exists so that the union will always be initialized, even when |
48 // it doesn't contain a value. Not initializing it has been observed to | 55 // it doesn't contain a value. Not initializing it has been observed to |
49 // trigger comiler warnings. | 56 // trigger comiler warnings. |
50 char empty_ = '\0'; | 57 char empty_ = '\0'; |
51 T value_; | 58 T value_; |
52 }; | 59 }; |
53 }; | 60 }; |
54 | 61 |
55 template <typename T> | 62 template <typename T> |
56 struct OptionalStorage<T, true> { | 63 struct OptionalStorage<T, true> { |
57 OptionalStorage() {} | 64 constexpr OptionalStorage() {} |
65 constexpr explicit OptionalStorage(const T& value) | |
66 : is_null_(false), value_(value) {} | |
67 constexpr explicit OptionalStorage(T&& value) | |
68 : is_null_(false), value_(std::move(value)) {} | |
69 template <class... Args> | |
70 constexpr explicit OptionalStorage(base::in_place_t, Args&&... args) | |
71 : is_null_(false), value_(std::forward<Args>(args)...) {} | |
58 // When T is trivially destructible (i.e. its destructor does nothing) there | 72 // When T is trivially destructible (i.e. its destructor does nothing) there |
danakj
2016/10/21 23:12:08
same
alshabalin
2016/10/22 07:47:51
Done.
| |
59 // is no need to call it. Explicitly defaulting the destructor means it's not | 73 // is no need to call it. Explicitly defaulting the destructor means it's not |
60 // user-provided. Those two together make this destructor trivial. | 74 // user-provided. Those two together make this destructor trivial. |
61 ~OptionalStorage() = default; | 75 ~OptionalStorage() = default; |
62 | 76 |
63 bool is_null_ = true; | 77 bool is_null_ = true; |
64 union { | 78 union { |
65 // |empty_| exists so that the union will always be initialized, even when | 79 // |empty_| exists so that the union will always be initialized, even when |
66 // it doesn't contain a value. Not initializing it has been observed to | 80 // it doesn't contain a value. Not initializing it has been observed to |
67 // trigger comiler warnings. | 81 // trigger comiler warnings. |
68 char empty_ = '\0'; | 82 char empty_ = '\0'; |
(...skipping 15 matching lines...) Expand all Loading... | |
84 // - Constructors do not use 'constexpr' as it is a C++14 extension. | 98 // - Constructors do not use 'constexpr' as it is a C++14 extension. |
85 // - 'constexpr' might be missing in some places for reasons specified locally. | 99 // - 'constexpr' might be missing in some places for reasons specified locally. |
86 // - No exceptions are thrown, because they are banned from Chromium. | 100 // - No exceptions are thrown, because they are banned from Chromium. |
87 // - All the non-members are in the 'base' namespace instead of 'std'. | 101 // - All the non-members are in the 'base' namespace instead of 'std'. |
88 template <typename T> | 102 template <typename T> |
89 class Optional { | 103 class Optional { |
90 public: | 104 public: |
91 using value_type = T; | 105 using value_type = T; |
92 | 106 |
93 constexpr Optional() = default; | 107 constexpr Optional() = default; |
94 Optional(base::nullopt_t) : Optional() {} | 108 constexpr Optional(base::nullopt_t) : Optional() {} |
95 | 109 |
96 Optional(const Optional& other) { | 110 Optional(const Optional& other) { |
97 if (!other.storage_.is_null_) | 111 if (!other.storage_.is_null_) |
98 Init(other.value()); | 112 Init(other.value()); |
99 } | 113 } |
100 | 114 |
101 Optional(Optional&& other) { | 115 Optional(Optional&& other) { |
102 if (!other.storage_.is_null_) | 116 if (!other.storage_.is_null_) |
103 Init(std::move(other.value())); | 117 Init(std::move(other.value())); |
104 } | 118 } |
105 | 119 |
106 Optional(const T& value) { Init(value); } | 120 constexpr Optional(const T& value) : storage_(value) {} |
107 | 121 |
108 Optional(T&& value) { Init(std::move(value)); } | 122 constexpr Optional(T&& value) : storage_(std::move(value)) {} |
109 | 123 |
110 template <class... Args> | 124 template <class... Args> |
111 explicit Optional(base::in_place_t, Args&&... args) { | 125 constexpr explicit Optional(base::in_place_t, Args&&... args) |
112 emplace(std::forward<Args>(args)...); | 126 : storage_(base::in_place, std::forward<Args>(args)...) {} |
113 } | |
114 | 127 |
115 ~Optional() = default; | 128 ~Optional() = default; |
116 | 129 |
117 Optional& operator=(base::nullopt_t) { | 130 Optional& operator=(base::nullopt_t) { |
118 FreeIfNeeded(); | 131 FreeIfNeeded(); |
119 return *this; | 132 return *this; |
120 } | 133 } |
121 | 134 |
122 Optional& operator=(const Optional& other) { | 135 Optional& operator=(const Optional& other) { |
123 if (other.storage_.is_null_) { | 136 if (other.storage_.is_null_) { |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 template <class T> | 478 template <class T> |
466 struct hash<base::Optional<T>> { | 479 struct hash<base::Optional<T>> { |
467 size_t operator()(const base::Optional<T>& opt) const { | 480 size_t operator()(const base::Optional<T>& opt) const { |
468 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); | 481 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); |
469 } | 482 } |
470 }; | 483 }; |
471 | 484 |
472 } // namespace std | 485 } // namespace std |
473 | 486 |
474 #endif // BASE_OPTIONAL_H_ | 487 #endif // BASE_OPTIONAL_H_ |
OLD | NEW |