1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef UTIL_CHRE_OPTIONAL_H_
18 #define UTIL_CHRE_OPTIONAL_H_
19 
20 #include <type_traits>
21 
22 namespace chre {
23 
24 /**
25  * This container keeps track of an optional object. The container is similar to
26  * std::optional introduced in C++17.
27  */
28 template<typename ObjectType>
29 class Optional {
30  public:
31   // Per the standard, a program that instantiates template optional for a
32   // reference type is ill-formed
33   static_assert(!std::is_reference<ObjectType>::value,
34                 "Optional references are not allowed");
35 
36   /**
37    * Default constructs the optional object with no initial value.
38    */
39   Optional() = default;
40 
41   /**
42    * Default copy constructor.
43    *
44    * @param object The object to copy construct from.
45    */
46   Optional(const Optional<ObjectType>& object) = default;
47 
48   /**
49    * Default copy constructor.
50    *
51    * @param object The object to copy construct from.
52    */
53   Optional(Optional<ObjectType>& object) = default;
54 
55   /**
56    * Constructs an optional instance with an initial value.
57    *
58    * @param object The initial value of the object.
59    */
60   Optional(const ObjectType& object);
61 
62   /**
63    * Constructs an optional instance with an initial value by moving it.
64    *
65    * @param object The instance of the initial object to take ownership of.
66    */
67   Optional(ObjectType&& object);
68 
69   /**
70    * Destructs the object. Calls through reset() to destroy the contained
71    * object before destructing this container.
72    */
73   ~Optional();
74 
75   /**
76    * @return Returns true if this container holds an object
77    */
78   bool has_value() const;
79 
80   /**
81    * Destroys any contained object, and marks this Optional as empty (i.e.
82    * has_value() will return false after this function returns)
83    */
84   void reset();
85 
86   /**
87    * Gets a reference to the contained object. Does not check that this optional
88    * contains a value, so this object will be uninitialized if has_value() is
89    * false.
90    */
91   ObjectType& value();
92   const ObjectType& value() const;
93 
94   /**
95    * Performs a move assignment operation to the underlying object managed by
96    * this container.
97    *
98    * @param other The other object to move from.
99    * @return Returns a reference to this object.
100    */
101   Optional<ObjectType>& operator=(ObjectType&& other);
102 
103   /**
104    * Performs a move assignment from one optional to another. Note that the
105    * other object still holds a value, but it is left in the moved-from state
106    * (as is the case in std::optional).
107    *
108    * @param other The other object to move.
109    * @return Returns a reference to this object.
110    */
111   Optional<ObjectType>& operator=(Optional<ObjectType>&& other);
112 
113   /**
114    * Performs a copy assignment operation to the underlying object managed by
115    * this container.
116    *
117    * @param other The other object to copy from.
118    * @return Returns a reference to this object.
119    */
120   Optional<ObjectType>& operator=(const ObjectType& other);
121 
122   /**
123    * Performs a copy assignment from one optional to another.
124    *
125    * @param other The other object to copy.
126    * @return Returns a reference to this object.
127    */
128   Optional<ObjectType>& operator=(const Optional<ObjectType>& other);
129 
130   /**
131    * Obtains a reference to the underlying object managed by this container.
132    * The behavior of this is undefined if has_value() returns false.
133    *
134    * @return Returns a reference to the underlying object tracked by this
135    *         container.
136    */
137   ObjectType& operator*();
138 
139   /**
140    * Obtains a const reference to the underlying object managed by this
141    * container. The behavior of this is undefined if has_value() returns false.
142    *
143    * @return Returns a const reference to the underlying object tracked by this
144    *         container.
145    */
146   const ObjectType& operator*() const;
147 
148   /**
149    * Obtains a pointer to the underlying object managed by this container. The
150    * object may not be well-formed if has_value() returns false.
151    *
152    * @return Returns a pointer to the underlying object tracked by this
153    *         container.
154    */
155   ObjectType *operator->();
156 
157   /**
158    * Obtains a const pointer to the underlying object managed by this container.
159    * The object may not be well-formed if has_value() returns false.
160    *
161    * @return Returns a const pointer to the underlying object tracked by this
162    *         container.
163    */
164   const ObjectType *operator->() const;
165 
166  private:
167   //! The optional object being tracked by this container.
168   typename std::aligned_storage<sizeof(ObjectType), alignof(ObjectType)>::type
169       mObject;
170 
171   //! Whether or not the object is set.
172   bool mHasValue = false;
173 
174   ObjectType& object();
175   const ObjectType& object() const;
176 
177   ObjectType *objectAddr();
178   const ObjectType *objectAddr() const;
179 };
180 
181 }  // namespace chre
182 
183 #include "chre/util/optional_impl.h"
184 
185 #endif  // UTIL_CHRE_OPTIONAL_H_
186