Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
optional.h
00001 ///\file 00002 00003 /****************************************************************************** 00004 The MIT License(MIT) 00005 00006 Embedded Template Library. 00007 https://github.com/ETLCPP/etl 00008 http://www.etlcpp.com 00009 00010 Copyright(c) 2015 jwellbelove 00011 00012 Permission is hereby granted, free of charge, to any person obtaining a copy 00013 of this software and associated documentation files(the "Software"), to deal 00014 in the Software without restriction, including without limitation the rights 00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00016 copies of the Software, and to permit persons to whom the Software is 00017 furnished to do so, subject to the following conditions : 00018 00019 The above copyright notice and this permission notice shall be included in all 00020 copies or substantial portions of the Software. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00028 SOFTWARE. 00029 ******************************************************************************/ 00030 00031 #ifndef __ETL_OPTIONAL__ 00032 #define __ETL_OPTIONAL__ 00033 00034 #include "platform.h " 00035 #include "alignment.h " 00036 #include "type_traits.h " 00037 #include "exception.h " 00038 #include "error_handler.h " 00039 00040 namespace etl 00041 { 00042 //***************************************************************************** 00043 /// A null option type. 00044 ///\ingroup utilities 00045 //***************************************************************************** 00046 class nullopt_t 00047 { 00048 public: 00049 00050 // Convertible to any type of null non-member pointer. 00051 template<class T> 00052 operator T*() const 00053 { 00054 return 0; 00055 } 00056 00057 private: 00058 00059 // Can't take address of nullopt. 00060 void operator&() const; 00061 }; 00062 00063 //***************************************************************************** 00064 /// A null option. 00065 ///\ingroup utilities 00066 //***************************************************************************** 00067 const nullopt_t nullopt = {}; 00068 00069 //*************************************************************************** 00070 /// Exception for optional. 00071 ///\ingroup list 00072 //*************************************************************************** 00073 class optional_exception : public exception 00074 { 00075 public: 00076 00077 optional_exception(string_type reason_, string_type file_name_, numeric_type line_number_) 00078 : exception(reason_, file_name_, line_number_) 00079 { 00080 } 00081 }; 00082 00083 //*************************************************************************** 00084 /// Invalid exception for optional. 00085 ///\ingroup list 00086 //*************************************************************************** 00087 class optional_invalid : public optional_exception 00088 { 00089 public: 00090 00091 optional_invalid(string_type file_name_, numeric_type line_number_) 00092 : optional_exception("optional: invalid", file_name_, line_number_) 00093 { 00094 } 00095 }; 00096 00097 //***************************************************************************** 00098 /// An optional type. 00099 /// If the optional type is not initialised then a type is not constructed. 00100 ///\tparam The type to store. 00101 ///\ingroup utilities 00102 //***************************************************************************** 00103 template <typename T> 00104 class optional 00105 { 00106 public: 00107 00108 //*************************************************************************** 00109 /// Constructor. 00110 //*************************************************************************** 00111 optional() 00112 : valid(false) 00113 { 00114 } 00115 00116 //*************************************************************************** 00117 /// Constructor with nullopt. 00118 //*************************************************************************** 00119 optional(etl::nullopt_t) 00120 : valid(false) 00121 { 00122 } 00123 00124 //*************************************************************************** 00125 /// Copy constructor. 00126 //*************************************************************************** 00127 optional(const optional& other) 00128 : valid(bool(other)) 00129 { 00130 if (valid) 00131 { 00132 ::new (storage.template get_address<T>()) T(other.value()); 00133 } 00134 } 00135 00136 //*************************************************************************** 00137 /// Constructor from value type. 00138 //*************************************************************************** 00139 optional(const T& value_) 00140 { 00141 ::new (storage.template get_address<T>()) T(value_); 00142 valid = true; 00143 } 00144 00145 //*************************************************************************** 00146 /// Destructor. 00147 //*************************************************************************** 00148 ~optional() 00149 { 00150 if (valid) 00151 { 00152 storage.template get_reference<T>().~T(); 00153 } 00154 } 00155 00156 //*************************************************************************** 00157 /// Assignment operator from nullopt. 00158 //*************************************************************************** 00159 optional& operator =(etl::nullopt_t) 00160 { 00161 if (valid) 00162 { 00163 storage.template get_reference<T>().~T(); 00164 valid = false; 00165 } 00166 00167 return *this; 00168 } 00169 00170 //*************************************************************************** 00171 /// Assignment operator from optional. 00172 //*************************************************************************** 00173 optional& operator =(const optional& other) 00174 { 00175 if (this != &other) 00176 { 00177 if (valid && !bool(other)) 00178 { 00179 storage.template get_reference<T>().~T(); 00180 valid = false; 00181 } 00182 else if (bool(other)) 00183 { 00184 if (valid) 00185 { 00186 storage.template get_reference<T>() = other.value(); 00187 } 00188 else 00189 { 00190 ::new (storage.template get_address<T>()) T(other.value()); 00191 valid = true; 00192 } 00193 } 00194 } 00195 00196 return *this; 00197 } 00198 00199 //*************************************************************************** 00200 /// Assignment operator from value type. 00201 //*************************************************************************** 00202 optional& operator =(const T& value_) 00203 { 00204 if (valid) 00205 { 00206 storage.template get_reference<T>() = value_; 00207 } 00208 else 00209 { 00210 ::new (storage.template get_address<T>()) T(value_); 00211 valid = true; 00212 } 00213 00214 return *this; 00215 } 00216 00217 //*************************************************************************** 00218 /// Pointer operator. 00219 //*************************************************************************** 00220 T* operator ->() 00221 { 00222 #if defined(ETL_DEBUG) 00223 ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); 00224 #endif 00225 00226 return storage.template get_address<T>(); 00227 } 00228 00229 //*************************************************************************** 00230 /// Pointer operator. 00231 //*************************************************************************** 00232 const T* operator ->() const 00233 { 00234 #if defined(ETL_DEBUG) 00235 ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); 00236 #endif 00237 00238 return storage.template get_address<T>(); 00239 } 00240 00241 //*************************************************************************** 00242 /// Dereference operator. 00243 //*************************************************************************** 00244 T& operator *() 00245 { 00246 #if defined(ETL_DEBUG) 00247 ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); 00248 #endif 00249 00250 return storage.template get_reference<T>(); 00251 } 00252 00253 //*************************************************************************** 00254 /// Dereference operator. 00255 //*************************************************************************** 00256 const T& operator *() const 00257 { 00258 #if defined(ETL_DEBUG) 00259 ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); 00260 #endif 00261 00262 return storage.template get_reference<T>(); 00263 } 00264 00265 //*************************************************************************** 00266 /// Bool conversion operator. 00267 //*************************************************************************** 00268 explicit operator bool() const 00269 { 00270 return valid; 00271 } 00272 00273 //*************************************************************************** 00274 /// Get a reference to the value. 00275 //*************************************************************************** 00276 T& value() 00277 { 00278 #if defined(ETL_DEBUG) 00279 ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); 00280 #endif 00281 00282 return storage.template get_reference<T>(); 00283 } 00284 00285 //*************************************************************************** 00286 /// Get a const reference to the value. 00287 //*************************************************************************** 00288 const T& value() const 00289 { 00290 #if defined(ETL_DEBUG) 00291 ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); 00292 #endif 00293 00294 return storage.template get_reference<T>(); 00295 } 00296 00297 //*************************************************************************** 00298 /// Gets the value or a default if no valid. 00299 //*************************************************************************** 00300 T value_or(T default_value) const 00301 { 00302 return valid ? value() : default_value; 00303 } 00304 00305 //*************************************************************************** 00306 /// Swaps this value with another. 00307 //*************************************************************************** 00308 void swap(optional& other) 00309 { 00310 optional temp(*this); 00311 *this = other; 00312 other = temp; 00313 } 00314 00315 private: 00316 00317 typename etl::aligned_storage_as<sizeof(T), T>::type storage; 00318 bool valid; 00319 }; 00320 } 00321 00322 //************************************************************************* 00323 /// Swaps the values. 00324 //************************************************************************* 00325 template <typename T> 00326 void swap(etl::optional<T>& lhs, etl::optional<T>& rhs) 00327 { 00328 lhs.swap(rhs); 00329 } 00330 00331 //*************************************************************************** 00332 /// Equality operator. 00333 //*************************************************************************** 00334 template <typename T> 00335 bool operator ==(const etl::optional<T>& lhs, const etl::optional<T>& rhs) 00336 { 00337 if (bool(lhs) != bool(rhs)) 00338 { 00339 return false; 00340 } 00341 else if (!bool(lhs) && !bool(rhs)) 00342 { 00343 return true; 00344 } 00345 else 00346 { 00347 return lhs.value() == rhs.value(); 00348 } 00349 } 00350 00351 //*************************************************************************** 00352 /// Less than operator. 00353 //*************************************************************************** 00354 template <typename T> 00355 bool operator <(const etl::optional<T>& lhs, const etl::optional<T>& rhs) 00356 { 00357 if (!bool(rhs)) 00358 { 00359 return false; 00360 } 00361 else if (!bool(lhs)) 00362 { 00363 return true; 00364 } 00365 else 00366 { 00367 return lhs.value() < rhs.value(); 00368 } 00369 } 00370 00371 //*************************************************************************** 00372 /// Equality operator. 00373 //*************************************************************************** 00374 template <typename T> 00375 bool operator ==(const etl::optional<T>& lhs, etl::nullopt_t) 00376 { 00377 return !bool(lhs); 00378 } 00379 00380 //*************************************************************************** 00381 /// Equality operator. 00382 //*************************************************************************** 00383 template <typename T> 00384 bool operator ==(etl::nullopt_t, const etl::optional<T>& rhs) 00385 { 00386 return false; 00387 } 00388 00389 //*************************************************************************** 00390 /// Less than operator. 00391 //*************************************************************************** 00392 template <typename T> 00393 bool operator <(const etl::optional<T>& lhs, etl::nullopt_t) 00394 { 00395 return !bool(lhs); 00396 } 00397 00398 //*************************************************************************** 00399 /// Less than operator. 00400 //*************************************************************************** 00401 template <typename T> 00402 bool operator <(etl::nullopt_t, const etl::optional<T>& rhs) 00403 { 00404 return bool(rhs); 00405 } 00406 00407 //*************************************************************************** 00408 /// Equality operator. 00409 //************************************************************************** 00410 template <typename T> 00411 bool operator ==(const etl::optional<T>& lhs, const T& rhs) 00412 { 00413 return bool(lhs) ? lhs.value() == rhs : false; 00414 } 00415 00416 //*************************************************************************** 00417 /// Equality operator. 00418 //************************************************************************** 00419 template <typename T> 00420 bool operator ==(const T& value, const etl::optional<T>& rhs) 00421 { 00422 return bool(rhs) ? rhs.value() == value : false; 00423 } 00424 00425 //*************************************************************************** 00426 /// Less than operator. 00427 //*************************************************************************** 00428 template <typename T> 00429 bool operator <(const etl::optional<T>& lhs, const T& rhs) 00430 { 00431 return bool(lhs) ? lhs.value() < rhs : true; 00432 } 00433 00434 //*************************************************************************** 00435 /// Make an optional. 00436 //*************************************************************************** 00437 template <typename T> 00438 etl::optional<typename etl::decay<T>::type> make_optional(T& value) 00439 { 00440 return etl::optional<typename etl::decay<T>::type>(value); 00441 } 00442 00443 #endif 00444
Generated on Tue Jul 12 2022 14:05:43 by
