/** * @file Optional.h * @brief Declaration of tc::Optional * @author Jack (jakcron) * @version 0.1 * @date 2019/01/06 **/ #pragma once #include namespace tc { /** * @class Optional * @brief A wrapper class, where the existence of the wrapped value is optional. **/ template class Optional { public: /** * @brief Default constructor * * This Optional shall be null initially. **/ Optional(); /** * @brief Initialising constructor with value to wrap * @param[in] value const T& Reference to value to wrap * * This Optional shall be not null initially. **/ Optional(const T& value); /** * @brief Copy constructor * @param[in] other const Optional& Reference to Optional object to copy * * This Optional shall be not null initially. **/ Optional(const Optional& other); /// Operator to wrap a value void operator=(const T& value); /// Operator to duplicate another Optional void operator=(const Optional& other); /** * @brief Access the wrapped value * @return T& reference to value **/ T& get() const; /** * @brief Determine if the Optional value doesn't exist * @return bool true if the value does not exist. **/ bool isNull() const; /** * @brief Determine if the Optional value exists * @return bool true if the value exists. **/ bool isSet() const; /** * @brief Release the wrapped value * * This will destroy the wrapped value and make this Optional null. * If this Optional is already null, this does nothing. **/ void makeNull(); private: std::shared_ptr mValue; }; template inline Optional::Optional() : mValue() { } template inline Optional::Optional(const T& value) : Optional() { *this = value; } template inline Optional::Optional(const Optional& other) : Optional() { *this = other; } template inline void Optional::operator=(const T& value) { // if mValue is null we need to allocate memory for it if (mValue == nullptr) { mValue = std::shared_ptr(new T); } // assign the value *mValue = value; } template inline void Optional::operator=(const Optional& other) { // if the other is null, then we make this null if (other.isNull()) { this->makeNull(); } // otherwise we have to assign this with the unwrapped mValue of other else { *this = other.get(); } } template inline T& Optional::get() const { return *mValue; } template inline bool Optional::isNull() const { return mValue == nullptr; } template inline bool Optional::isSet() const { return mValue != nullptr; } template inline void Optional::makeNull() { mValue.reset(); } } // namespace tc