OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef BASE_OPTIONAL_H_ | |
6 #define BASE_OPTIONAL_H_ | |
7 | |
8 #include "base/logging.h" | |
9 #include "base/memory/aligned_memory.h" | |
10 | |
11 namespace base { | |
12 | |
13 // Specification: | |
14 // http://en.cppreference.com/w/cpp/experimental/optional/nullopt_t | |
15 struct nullopt_t { | |
16 explicit nullopt_t(int _) { } | |
danakj
2015/11/19 20:55:46
i recently discovered the style guide now says you
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Done.
| |
17 }; | |
18 | |
19 // Specification: | |
20 // http://en.cppreference.com/w/cpp/experimental/optional/nullopt | |
21 const nullopt_t nullopt(0); | |
22 | |
23 // base::Optional is a Chromium version of the C++ library experimental optional | |
24 // class: http://en.cppreference.com/w/cpp/experimental/optional/optional | |
25 // The following methods are not implemented: | |
26 // - All methods using rvalue reference (ie. && operator). | |
danakj
2015/11/19 20:55:46
I think that I'd like to wait on this until we all
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Kind of. I've updated the list. Let me know how th
| |
27 // Thus, instead of operator=(U&&), operator=(const T&) is implemented. | |
28 // - Two constructor forms are not implemented. | |
29 // - swap() and emplace() are not implemented. | |
30 // - Private member |val| is not implemented. | |
31 // - Some non-member functions, classes and helper objects are implemented but | |
32 // not all. | |
33 template <typename T> | |
34 class Optional { | |
35 public: | |
36 Optional() : is_null_(true) { } | |
37 Optional(base::nullopt_t opt) : Optional() { } | |
38 | |
39 Optional(const Optional& other) | |
danakj
2015/12/10 23:45:45
Can you add a Optional(Optional&&) constructor?
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
40 : Optional() { | |
41 if (!other.is_null_) | |
42 init(other.value()); | |
43 } | |
44 | |
45 Optional(const T& value) | |
danakj
2015/12/10 23:45:46
And an Optional(T&&) constructor
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Done.
| |
46 : Optional() { | |
47 init(value); | |
48 } | |
49 | |
50 // The difference between the specification and this method is that this | |
51 // implementation doesn't use std::is_trivially_destructible. | |
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Is it okay to use std::is_trivially_destructible?
| |
52 ~Optional() { | |
53 free_if_needed(); | |
54 } | |
55 | |
56 Optional& operator=(base::nullopt_t opt) { | |
57 free_if_needed(); | |
58 return *this; | |
59 } | |
60 | |
61 Optional& operator=(const Optional& other) { | |
danakj
2015/12/10 23:45:45
can you add operator=(Optional&&)
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
62 if (other.is_null_) { | |
63 free_if_needed(); | |
64 return *this; | |
65 } | |
66 | |
67 init_or_assign(other.value()); | |
68 return *this; | |
69 } | |
70 | |
71 // This method is not part of the current C++ standard. It is instead defined | |
72 // as: | |
73 // template <class U> | |
74 // optional& operator=(U&& value); | |
75 Optional& operator=(const T& value) { | |
danakj
2015/12/10 23:45:45
Let's make this take a T&&
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done. I've included the per-spec std::enable_if.
| |
76 init_or_assign(value); | |
77 return *this; | |
78 } | |
79 | |
80 const T* operator->() const { | |
81 DCHECK(!is_null_); | |
82 return buffer_.template data_as<T>(); | |
83 } | |
84 | |
85 T* operator->() { | |
86 DCHECK(!is_null_); | |
87 return buffer_.template data_as<T>(); | |
88 } | |
89 | |
90 const T& operator*() const { | |
91 return value(); | |
92 } | |
93 | |
94 T& operator*() { | |
95 return value(); | |
96 } | |
97 | |
98 explicit operator bool() const { return !is_null_; } | |
danakj
2015/12/10 23:45:46
explicit operator is banned: http://chromium-cpp.a
mlamouri (slow - plz ping)
2016/02/29 22:31:26
I couldn't get that to work. The issue is that I c
| |
99 | |
100 T& value() { | |
danakj
2015/12/10 23:45:45
can you ref-quality this with &
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Done.
| |
101 DCHECK(!is_null_); | |
102 return *buffer_.template data_as<T>(); | |
103 } | |
104 | |
105 const T& value() const { | |
danakj
2015/12/10 23:45:45
and this with &,
and add the T&& versions of valu
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
106 DCHECK(!is_null_); | |
107 return *buffer_.template data_as<T>(); | |
108 } | |
109 | |
110 template <class U> | |
111 T value_or(U&& default_value) const { | |
danakj
2015/12/10 23:45:46
can add the non-const version of this method too
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
112 return is_null_ ? default_value : value(); | |
113 } | |
114 | |
115 bool operator==(const Optional& other) const { | |
116 return (is_null_ && other.is_null_) || | |
117 (!is_null_ && !other.is_null_ && value() == other.value()); | |
118 } | |
119 | |
120 bool operator!=(const Optional& other) const { | |
121 return !this->operator==(other); | |
122 } | |
123 | |
124 private: | |
125 void init(const T& value) { | |
126 DCHECK(is_null_); | |
127 new (buffer_.template data_as<T>()) T(value); | |
128 is_null_ = false; | |
129 } | |
130 | |
131 void init_or_assign(const T& value) { | |
132 if (is_null_) | |
133 init(value); | |
134 else | |
135 *buffer_.template data_as<T>() = value; | |
136 } | |
137 | |
138 void free_if_needed() { | |
139 if (is_null_) | |
140 return; | |
141 buffer_.template data_as<T>()->~T(); | |
142 is_null_ = true; | |
143 } | |
144 | |
145 bool is_null_; | |
146 base::AlignedMemory<sizeof(T), ALIGNOF(T)> buffer_; | |
147 }; | |
148 | |
149 } // namespace base | |
150 | |
151 #endif // BASE_OPTIONAL_H_ | |
OLD | NEW |