// ********************************************************************** // // Copyright (c) 2003-2018 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #ifndef ICE_UTIL_OPTIONAL_H #define ICE_UTIL_OPTIONAL_H #ifndef ICE_CPP11_MAPPING #include namespace IceUtilInternal { struct NoneType { }; } namespace IceUtil { /** A sentinel value used to indicate that no optional value was provided. */ const IceUtilInternal::NoneType None = {}; /** Encapsulates an optional value, which may or may not be present. */ template class Optional { public: typedef T element_type; /** * Constructs an empty optional with no value. */ Optional() : _isSet(false) { } /** * Constructs an empty optional with no value. */ Optional(IceUtilInternal::NoneType) : _isSet(false) { } /** * Constructs an optional with the given value. * @param p The initial value. */ template Optional(Y p) : _value(p), _isSet(true) { } /** * Constructs an optional as a copy of the given optional. * @param r The source optional. */ template Optional(const Optional& r) : _value(r._value), _isSet(r._isSet) { } ~Optional() { } /** * Resets this optional to have no value. */ Optional& operator=(IceUtilInternal::NoneType) { _value = T(); _isSet = false; return *this; } /** * Resets this optional to have the given value. * @param p The new value. */ template Optional& operator=(Y p) { _value = p; _isSet = true; return *this; } /** * Resets this optional to be a copy of the given optional. * @param r The source optional. */ template Optional& operator=(const Optional& r) { _value = r._value; _isSet = r._isSet; return *this; } /** * Resets this optional to be a copy of the given optional. * @param r The source optional. */ Optional& operator=(const Optional& r) { _value = r._value; _isSet = r._isSet; return *this; } /** * Obtains the current value. * @return The current value. * @throws OptionalNotSetException if this optional has no value. */ const T& value() const { checkIsSet(); return _value; } /** * Obtains the current value. * @return The current value. * @throws OptionalNotSetException if this optional has no value. */ T& value() { checkIsSet(); return _value; } /** * Obtains the current value. * @return The current value. * @throws OptionalNotSetException if this optional has no value. */ const T& get() const { return value(); } /** * Obtains the current value. * @return The current value. * @throws OptionalNotSetException if this optional has no value. */ T& get() { return value(); } /** * Obtains a pointer to the current value. * @return A pointer to the current value. * @throws OptionalNotSetException if this optional has no value. */ const T* operator->() const { return &value(); } /** * Obtains a pointer to the current value. * @return A pointer to the current value. * @throws OptionalNotSetException if this optional has no value. */ T* operator->() { return &value(); } /** * Obtains the current value. * @return The current value. * @throws OptionalNotSetException if this optional has no value. */ const T& operator*() const { return value(); } /** * Obtains the current value. * @return The current value. * @throws OptionalNotSetException if this optional has no value. */ T& operator*() { return value(); } /** * Determines whether this optional has a value. * @return True if the optional has a value, false otherwise. */ operator bool() const { return _isSet; } /** * Determines whether this optional has a value. * @return True if the optional does not have a value, false otherwise. */ bool operator!() const { return !_isSet; } /** * Exchanges the state of this optional with another one. * @param other The optional value with which to swap. */ void swap(Optional& other) { std::swap(_isSet, other._isSet); std::swap(_value, other._value); } /// \cond INTERNAL void __setIsSet() { _isSet = true; } /// \endcond private: void checkIsSet() const { if(!_isSet) { throwOptionalNotSetException(__FILE__, __LINE__); } } void throwOptionalNotSetException(const char *, int) const; T _value; bool _isSet; }; /** * Constructs an optional from the given value. * @param v The optional's initial value. * @return A new optional object. */ template inline Optional makeOptional(const T& v) { return Optional(v); } /// \cond INTERNAL template inline void Optional::throwOptionalNotSetException(const char* file, int line) const { throw OptionalNotSetException(file, line); } /// \endcond template inline bool operator==(const Optional& lhs, const Optional& rhs) { if(lhs && rhs) { return *lhs == *rhs; } else { return !lhs && !rhs; } } template inline bool operator!=(const Optional& lhs, const Optional& rhs) { return !operator==(lhs, rhs); } template inline bool operator<(const Optional& lhs, const Optional& rhs) { if(lhs && rhs) { return *lhs < *rhs; } else { return !lhs && rhs; } } template inline bool operator<=(const Optional& lhs, const Optional& rhs) { return lhs < rhs || lhs == rhs; } template inline bool operator>(const Optional& lhs, const Optional& rhs) { return !(lhs < rhs || lhs == rhs); } template inline bool operator>=(const Optional& lhs, const Optional& rhs) { return !(lhs < rhs); } // Optional vs Y template inline bool operator==(const Optional& lhs, const Y& rhs) { if(!lhs) { return false; } else { return *lhs == rhs; } } template inline bool operator!=(const Optional& lhs, const Y& rhs) { return !operator==(lhs, rhs); } template inline bool operator<(const Optional& lhs, const Y& rhs) { if(lhs) { return *lhs < rhs; } else { return true; } } template inline bool operator<=(const Optional& lhs, const Y& rhs) { return lhs < rhs || lhs == rhs; } template inline bool operator>(const Optional& lhs, const Y& rhs) { return !(lhs < rhs || lhs == rhs); } template inline bool operator>=(const Optional& lhs, const Y& rhs) { return !(lhs < rhs); } // Y vs Optional template inline bool operator==(const Y& lhs, const Optional& rhs) { if(!rhs) { return false; } else { return lhs == *rhs; } } template inline bool operator!=(const Y& lhs, const Optional& rhs) { return !operator==(lhs, rhs); } template inline bool operator<(const Y& lhs, const Optional& rhs) { if(rhs) { return lhs < *rhs; } else { return false; } } template inline bool operator<=(const Y& lhs, const Optional& rhs) { return lhs < rhs || lhs == rhs; } template inline bool operator>(const Y& lhs, const Optional& rhs) { return !(lhs < rhs || lhs == rhs); } template inline bool operator>=(const Y& lhs, const Optional& rhs) { return !(lhs < rhs); } } #endif #endif