DYT/Tool/matlab/include/MatlabDataArray/Optional.hpp

339 lines
9.9 KiB
C++
Raw Permalink Normal View History

2024-11-22 15:19:31 +00:00
/* Copyright 2017 The MathWorks, Inc. */
#ifndef MATLAB_DATA_OPTIONAL_HPP_
#define MATLAB_DATA_OPTIONAL_HPP_
#include "detail/publish_util.hpp"
#include <stdexcept>
namespace matlab {
namespace data {
typedef struct nullopt {
explicit nullopt(int) {}
} nullopt_t;
/**
* The class template optional manages an optional contained value, i.e. a value that may or may not be present.
*/
template<typename T>
class optional {
public:
typedef T value_type;
/**
* Default constructor
*
* Set missing flag to true to indicate that the object
* does not contain a value
* @throw none
*/
optional() MW_NOEXCEPT {
fMissing = true;
}
/**
* Default constructor
*
* Set missing flag to true to indicate that the object
* does not contain a value
* @throw None
*/
optional(nullopt_t) MW_NOEXCEPT {
fMissing = true;
}
/**
* Default constructor
*
* Set missing flag to true to indicate that the object
* does not contain a value
* @throw None
*/
optional(std::nullptr_t) MW_NOEXCEPT{
fMissing = true;
}
/**
* Copy constructor
*
* @param - rhs Reference value to be copied
* @return - newly constructed optional object
* @throw none
*/
optional(const optional& other) MW_NOEXCEPT {
fMissing = other.fMissing;
if (!fMissing) {
fData = other.fData;
}
}
/**
* Move constructor
*
* @param - rhs optional value to be moved
* @return - newly constructed optional
* @throw none
*/
optional(optional&& other) MW_NOEXCEPT {
fMissing = std::move(other.fMissing);
if (!fMissing) {
fData = std::move(other.fData);
}
}
/**
* Move constructor
*
* @param - rhs value of type T to be moved
* @return - newly constructed optional
* @throw none
*/
optional(T&& value) MW_NOEXCEPT
: fData(std::move(value)) {
fMissing = false;
}
/**
* Copy assignment
*
* @param - rhs optional value to be copied
* @return - updated optional
* @throw none
*/
optional<T>& operator=(const optional<T>& other) MW_NOEXCEPT {
if (fMissing && other.fMissing) {
return *this;
}
if (!fMissing && other.fMissing) {
fMissing = true;
}
if (!other.fMissing) {
fData = other.fData;
fMissing = false;
}
return *this;
}
/**
* Move assignment
*
* @param - rhs optional value to be moved
* @return - updated optional
* @throw none
*/
optional<T>& operator=(optional<T>&& other) MW_NOEXCEPT {
if (fMissing && other.fMissing) {
return *this;
}
if (!fMissing && other.fMissing) {
fMissing = true;
}
if (!other.fMissing) {
fData = std::move(other.fData);
fMissing = false;
}
return *this;
}
/**
* Move assignment
*
* @param - rhs value of type value_type to be moved
* @return - updated optional
* @throw none
*/
optional<T>& operator=(T&& value) MW_NOEXCEPT {
fMissing = false;
fData = value;
return *this;
}
/**
* Copy assignment
*
* @param - rhs value of type value_type to be copied
* @return - updated optional
* @throw none
*/
optional<T>& operator=(const T& value) MW_NOEXCEPT {
fMissing = false;
fData = value;
return *this;
}
/**
* Operator->
*
* @return - return const value contained in optional
* @throw - std::runtime_error if there is no value
*/
const T* operator->() const {
if (fMissing) {
throw std::runtime_error("Missing string value");
}
return fData;
}
/**
* Operator->
*
* @return - return value contained in optional
* @throw - std::runtime_error if there is no value
*/
T * operator->() {
if (fMissing) {
throw std::runtime_error("Missing string value");
}
return &fData;
}
/**
* Operator*
*
* @return - return const value contained in optional
* @throw - std::runtime_error if there is no value
*/
const T& operator*() const {
if (fMissing) {
throw std::runtime_error("Missing string value");
}
return const_cast<T&>(fData);
}
/**
* Operator*
*
* @return - value contained in optional
* @throw - std::runtime_error if there is no value
*/
T& operator*() {
if (fMissing) {
throw std::runtime_error("Missing string value");
}
return fData;
}
/**
* Check if this instance of optional contains a value
*
* @return - true if contains a value, false otherwise
* @throw none
*/
explicit operator bool() const MW_NOEXCEPT {
return !fMissing;
}
/**
* Cast optional<T> value to T
*
* @return value contained in optional<T> if such exists
* &throw none
*/
operator T() const {
if (fMissing) {
throw std::runtime_error("Missing string value");
}
return fData;
}
/**
* Check if this instance of optional contains a value
*
* @return - true if contains a value, false otherwise
* @throw none
*/
bool has_value() const MW_NOEXCEPT {
return !fMissing;
}
/**
* Swap value of this optional instance with value
* contained in the parameter
*
* @param - optional value to swap with
* @throw none
*/
void swap(optional &other) MW_NOEXCEPT {
if (fMissing && other.fMissing) {
return;
}
if (!fMissing && !other) {
other = std::move(fData);
fMissing = true;
}
else if (fMissing && other) {
fData = std::move(*other);
other.reset();
} else {
auto tmp = fData;
fData = *other;
other = std::move(tmp);
}
}
/**
* Reset optional value to missing
*
* @throw none
*/
void reset() MW_NOEXCEPT {
fMissing = true;
}
~optional() {}
private:
bool fMissing;
T fData;
};
// non-member functions
// To be consistent with MATLAB string behavior, missing values do not compare equal to anything
template<class T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs) MW_NOEXCEPT {
if (lhs.has_value() && rhs.has_value()) {
return (*lhs == *rhs);
} else {
return false;
}
}
template< class T >
bool operator==(const optional<T>& opt, nullopt_t) MW_NOEXCEPT {
return false;
}
template<class T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs) MW_NOEXCEPT {
return (!(lhs == rhs));
}
template<class T>
bool operator==(const optional<T>& opt, const T& value) MW_NOEXCEPT {
if (!opt) {
return false;
}
return (*opt == value);
}
template< class T >
bool operator!=(const optional<T>& opt, nullopt_t) MW_NOEXCEPT {
return true;
}
template<class T>
bool operator!=(const optional<T>& opt, const T& value) MW_NOEXCEPT {
return (!(opt == value));
}
} // data
} // matlab
#endif