7af2ce88bbc5cd0bd6f8fd9fbe19b5abe8926e74
[platform/core/uifw/vulkan-wsi-tizen.git] / util / optional.hpp
1 /*
2  * Copyright (c) 2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #pragma once
26 #include <cassert>
27
28 namespace util
29 {
30 template <typename T>
31 class optional
32 {
33 public:
34    using value_type = T;
35
36    optional(const optional &) = delete;
37    optional &operator=(const optional &) = delete;
38
39    /**
40     * @brief Construct an empty optional object.
41     */
42    optional() = default;
43
44    /**
45     * @brief Construct an optional object with a value.
46     *
47     * @param val The value that will be placed in the optional.
48     */
49    optional(value_type &&val) noexcept
50       : m_has_value(true), m_value(std::move(val))
51    {
52    }
53
54    /**
55     * @brief Construct a new optional object from another optional
56     *
57     * @param opt The optional object that will be moved
58     */
59    optional(optional &&opt)
60       : m_has_value(opt.m_has_value)
61    {
62       if (opt.m_has_value)
63       {
64          m_value = std::move(opt.m_value);
65          opt.m_has_value = false;
66       }
67       else
68       {
69          m_value = T{};
70       }
71    }
72
73    /**
74     * @brief Check if optional has a value.
75     *
76     * @return true If the optional has a value.
77     * @return false If the optional does not have a value.
78     */
79    bool has_value() const noexcept
80    {
81       return m_has_value;
82    }
83
84    /**
85     * @brief Return the value in the optional. It is only
86     *        valid to call this function if optional has a value.
87     *
88     * @return value_type& The value that is in the optional
89     */
90    value_type &value() noexcept
91    {
92       assert(has_value());
93       return m_value;
94    }
95
96    /**
97     * @brief Clears the value from the optional
98     *
99     */
100    void reset() noexcept
101    {
102       m_has_value = false;
103       m_value = T{};
104    }
105
106    /**
107     * @brief Reassign/assign the value in the optional.
108     *
109     * @return optional& This optional object with the value.
110     */
111    optional &set(T &&val) noexcept
112    {
113       m_value = std::move(val);
114       m_has_value = true;
115       return *this;
116    }
117
118    optional &set(const T &val) noexcept
119    {
120       m_value = val;
121       m_has_value = true;
122       return *this;
123    }
124
125    /**
126     * @brief Return the value in the optional, same as value()
127     *
128     * @return value_type& The value in the optional
129     */
130    value_type &operator*() noexcept
131    {
132       assert(has_value());
133       return m_value;
134    }
135
136    /**
137     * @brief Return the value in the optional as pointer.
138     *
139     * @return value_type* The value in the optional
140     */
141    value_type *operator->() noexcept
142    {
143       assert(has_value());
144       return &m_value;
145    }
146
147    /**
148     * @brief Reassign/assign the value in the optional
149     *
150     * @param val The value to assign to this optional
151     * @return optional& This optional object with the value
152     */
153    optional &operator=(value_type &&val) noexcept
154    {
155       m_has_value = true;
156       m_value = std::move(val);
157
158       return *this;
159    }
160
161    /**
162     * @brief Construct a new optional object from another optional
163     *
164     * @param opt The optional object that will be moved
165     * @return optional& This optional object with the value
166     */
167    optional &operator=(optional &&opt)
168    {
169       if (this != &opt)
170       {
171          if (opt.m_has_value)
172          {
173             m_has_value = true;
174             m_value = std::move(opt.m_value);
175             opt.m_has_value = false;
176          }
177          else
178          {
179             m_value = T{};
180             m_has_value = false;
181          }
182       }
183
184       return *this;
185    }
186
187 private:
188    bool m_has_value{false};
189    T m_value{};
190 };
191
192 template <typename T, typename... Args>
193 inline optional<T> make_optional(Args &&...args)
194 {
195    return optional<T>{T(std::forward<Args>(args)...)};
196 }
197 }