Aleksandrs Gumenuks / MaximInterface_Extended

Dependents:   mbed_DS28EC20_GPIO

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers optional.hpp Source File

optional.hpp

00001 /*******************************************************************************
00002 * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #ifndef MaximInterface_optional
00034 #define MaximInterface_optional
00035 
00036 #include "SafeBool.hpp"
00037 
00038 // Include for std::swap.
00039 #include <algorithm>
00040 #include <utility>
00041 
00042 namespace MaximInterface {
00043 
00044 struct nullopt_t {
00045   explicit nullopt_t(int) {}
00046 };
00047 
00048 static const nullopt_t nullopt(0);
00049 
00050 /// @brief Optional value container similar to std::optional.
00051 /// @details
00052 /// To prevent the need for aligned storage, this implementation imposes that
00053 /// types must be DefaultConstructible, CopyConstructible, and CopyAssignable.
00054 /// No exceptions are thrown when accessing a valueless optional.
00055 template <typename T> class optional {
00056 public:
00057   typedef T value_type;
00058 
00059   optional() : value_(), has_value_(false) {}
00060   
00061   optional(nullopt_t) : value_(), has_value_(false) {}
00062 
00063   optional(const T & value) : value_(value), has_value_(true) {}
00064 
00065   template <typename U>
00066   explicit optional(const optional<U> & other)
00067       : value_(other.value_), has_value_(other.has_value_) {}
00068 
00069   optional & operator=(nullopt_t) {
00070     reset();
00071     return *this;
00072   }
00073 
00074   optional & operator=(const T & value) {
00075     value_ = value;
00076     has_value_ = true;
00077     return *this;
00078   }
00079 
00080   template <typename U> optional & operator=(const optional<U> & other) {
00081     if (has_value_ || other.has_value_) {
00082       value_ = other.value_;
00083       has_value_ = other.has_value_;
00084     }
00085     return *this;
00086   }
00087 
00088   bool has_value() const { return has_value_; }
00089   
00090   operator SafeBool() const { return makeSafeBool(has_value()); }
00091 
00092   const T & value() const { return value_; }
00093   
00094   T & value() {
00095     return const_cast<T &>(static_cast<const optional &>(*this).value());
00096   }
00097   
00098   const T & operator*() const { return value(); }
00099   
00100   T & operator*() {
00101     return const_cast<T &>(static_cast<const optional &>(*this).operator*());
00102   }
00103   
00104   const T * operator->() const { return &value(); }
00105   
00106   T * operator->() {
00107     return const_cast<T *>(static_cast<const optional &>(*this).operator->());
00108   }
00109 
00110   const T & value_or(const T & default_value) const {
00111     return has_value() ? value() : default_value;
00112   }
00113 
00114   void swap(optional & other) {
00115     if (has_value_ || other.has_value_) {
00116       using std::swap;
00117       swap(value_, other.value_);
00118       swap(has_value_, other.has_value_);
00119     }
00120   }
00121 
00122   void reset() {
00123     if (has_value_) {
00124       has_value_ = false;
00125       value_ = T();
00126     }
00127   }
00128 
00129 private:
00130   T value_;
00131   bool has_value_;
00132 };
00133 
00134 template <typename T> optional<T> make_optional(const T & value) {
00135   return value;
00136 }
00137 
00138 template <typename T> void swap(optional<T> & lhs, optional<T> & rhs) {
00139   lhs.swap(rhs);
00140 }
00141 
00142 template <typename T, typename U>
00143 bool operator==(const optional<T> & lhs, const optional<U> & rhs) {
00144   if (lhs.has_value() != rhs.has_value()) {
00145     return false;
00146   }
00147   if (!lhs.has_value()) {
00148     return true;
00149   }
00150   return lhs.value() == rhs.value();
00151 }
00152 
00153 template <typename T, typename U>
00154 bool operator!=(const optional<T> & lhs, const optional<U> & rhs) {
00155   if (lhs.has_value() != rhs.has_value()) {
00156     return true;
00157   }
00158   if (!lhs.has_value()) {
00159     return false;
00160   }
00161   return lhs.value() != rhs.value();
00162 }
00163 
00164 template <typename T, typename U>
00165 bool operator<(const optional<T> & lhs, const optional<U> & rhs) {
00166   if (!rhs.has_value()) {
00167     return false;
00168   }
00169   if (!lhs.has_value()) {
00170     return true;
00171   }
00172   return lhs.value() < rhs.value();
00173 }
00174 
00175 template <typename T, typename U>
00176 bool operator<=(const optional<T> & lhs, const optional<U> & rhs) {
00177   if (!lhs.has_value()) {
00178     return true;
00179   }
00180   if (!rhs.has_value()) {
00181     return false;
00182   }
00183   return lhs.value() <= rhs.value();
00184 }
00185 
00186 template <typename T, typename U>
00187 bool operator>(const optional<T> & lhs, const optional<U> & rhs) {
00188   if (!lhs.has_value()) {
00189     return false;
00190   }
00191   if (!rhs.has_value()) {
00192     return true;
00193   }
00194   return lhs.value() > rhs.value();
00195 }
00196 
00197 template <typename T, typename U>
00198 bool operator>=(const optional<T> & lhs, const optional<U> & rhs) {
00199   if (!rhs.has_value()) {
00200     return true;
00201   }
00202   if (!lhs.has_value()) {
00203     return false;
00204   }
00205   return lhs.value() >= rhs.value();
00206 }
00207 
00208 template <typename T> bool operator==(const optional<T> & opt, nullopt_t) {
00209   return !opt.has_value();
00210 }
00211 
00212 template <typename T> bool operator==(nullopt_t, const optional<T> & opt) {
00213   return operator==(opt, nullopt);
00214 }
00215 
00216 template <typename T> bool operator!=(const optional<T> & opt, nullopt_t) {
00217   return !operator==(opt, nullopt);
00218 }
00219 
00220 template <typename T> bool operator!=(nullopt_t, const optional<T> & opt) {
00221   return operator!=(opt, nullopt);
00222 }
00223 
00224 template <typename T> bool operator<(const optional<T> &, nullopt_t) {
00225   return false;
00226 }
00227 
00228 template <typename T> bool operator<(nullopt_t, const optional<T> & opt) {
00229   return opt.has_value();
00230 }
00231 
00232 template <typename T> bool operator<=(const optional<T> & opt, nullopt_t) {
00233   return !operator>(opt, nullopt);
00234 }
00235 
00236 template <typename T> bool operator<=(nullopt_t, const optional<T> & opt) {
00237   return !operator>(nullopt, opt);
00238 }
00239 
00240 template <typename T> bool operator>(const optional<T> & opt, nullopt_t) {
00241   return operator<(nullopt, opt);
00242 }
00243 
00244 template <typename T> bool operator>(nullopt_t, const optional<T> & opt) {
00245   return operator<(opt, nullopt);
00246 }
00247 
00248 template <typename T> bool operator>=(const optional<T> & opt, nullopt_t) {
00249   return !operator<(opt, nullopt);
00250 }
00251 
00252 template <typename T> bool operator>=(nullopt_t, const optional<T> & opt) {
00253   return !operator<(nullopt, opt);
00254 }
00255 
00256 template <typename T, typename U>
00257 bool operator==(const optional<T> & opt, const U & value) {
00258   return opt.has_value() ? opt.value() == value : false;
00259 }
00260 
00261 template <typename T, typename U>
00262 bool operator==(const T & value, const optional<U> & opt) {
00263   return operator==(opt, value);
00264 }
00265 
00266 template <typename T, typename U>
00267 bool operator!=(const optional<T> & opt, const U & value) {
00268   return opt.has_value() ? opt.value() != value : true;
00269 }
00270 
00271 template <typename T, typename U>
00272 bool operator!=(const T & value, const optional<U> & opt) {
00273   return operator!=(opt, value);
00274 }
00275 
00276 template <typename T, typename U>
00277 bool operator<(const optional<T> & opt, const U & value) {
00278   return opt.has_value() ? opt.value() < value : true;
00279 }
00280 
00281 template <typename T, typename U>
00282 bool operator<(const T & value, const optional<U> & opt) {
00283   return opt.has_value() ? value < opt.value() : false;
00284 }
00285 
00286 template <typename T, typename U>
00287 bool operator<=(const optional<T> & opt, const U & value) {
00288   return opt.has_value() ? opt.value() <= value : true;
00289 }
00290 
00291 template <typename T, typename U>
00292 bool operator<=(const T & value, const optional<U> & opt) {
00293   return opt.has_value() ? value <= opt.value() : false;
00294 }
00295 
00296 template <typename T, typename U>
00297 bool operator>(const optional<T> & opt, const U & value) {
00298   return opt.has_value() ? opt.value() > value : false;
00299 }
00300 
00301 template <typename T, typename U>
00302 bool operator>(const T & value, const optional<U> & opt) {
00303   return opt.has_value() ? value > opt.value() : true;
00304 }
00305 
00306 template <typename T, typename U>
00307 bool operator>=(const optional<T> & opt, const U & value) {
00308   return opt.has_value() ? opt.value() >= value : false;
00309 }
00310 
00311 template <typename T, typename U>
00312 bool operator>=(const T & value, const optional<U> & opt) {
00313   return opt.has_value() ? value >= opt.value() : true;
00314 }
00315 
00316 } // namespace MaximInterface
00317 
00318 #endif