Skip to content

Commit

Permalink
latest from coda-oss
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Smith committed Jan 17, 2022
1 parent 06716b7 commit d81a4d1
Show file tree
Hide file tree
Showing 7 changed files with 614 additions and 455 deletions.
324 changes: 6 additions & 318 deletions externals/coda-oss/modules/c++/coda_oss/include/coda_oss/optional.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,331 +27,19 @@
#include <utility>
#include <stdexcept>

// Simple version of std::optional since that doesn't exist until C++17.
//
// This doesn't even TRY to match the actual C++17 specification,
// it only tries to minimize code changes.
//
// http://en.cppreference.com/w/cpp/utility/Optional

#include "coda_oss/namespace_.h"
namespace coda_oss
{
namespace details
{
inline void throw_bad_optional_access()
{
throw std::logic_error("No value for optional<>."); // TODO: std::bad_optional_access
}
}
#include "coda_oss/optional_.h"

template <typename T>
class optional final
namespace coda_oss
{
T value_;
bool has_value_ = false;

void check_has_value() const
{
if (!has_value())
{
details::throw_bad_optional_access();
}
}

public:
using value_type = T;

#if defined(_MSC_VER) && _PREFAST_ // Visual Studio /analyze
__pragma(warning(push))
__pragma(warning(disable: 26495)) // Variable '...' is uninitialized. Always initialize a member variable(type.6).
#endif
optional() noexcept
{
}
#if defined(_MSC_VER) && _PREFAST_
__pragma(warning(pop))
#endif
optional(const value_type& v) : value_(v), has_value_(true)
{
}
#if defined(_MSC_VER) && _PREFAST_ // Visual Studio /analyze
__pragma(warning(push))
__pragma(warning(disable: 26495)) // Variable '...' is uninitialized. Always initialize a member variable(type.6).
#endif
optional(const optional& other) : has_value_(other.has_value_)
{
if (has_value())
{
value_ = other.value_;
}
}
#if defined(_MSC_VER) && _PREFAST_
__pragma(warning(pop))
#endif

template <typename... Args> // https://en.cppreference.com/w/cpp/utility/Optional/emplace
T& emplace(Args&&... args)
{
value_ = value_type(std::forward<Args>(args)...);
has_value_ = true;
return value_;
}

template<typename U = T> // https://en.cppreference.com/w/cpp/utility/optional/operator%3D
optional& operator=(U&& value) noexcept
{
value_ = std::forward<U>(value);
has_value_ = true;
return *this;
}

bool has_value() const noexcept
{
return has_value_;
}
explicit operator bool() const noexcept
{
return has_value();
}

void reset() noexcept
{
has_value_ = false;
}

// https://en.cppreference.com/w/cpp/utility/optional/value
T& value() &
{
check_has_value();
return value_;
}
const T& value() const&
{
check_has_value();
return value_;
}
T&& value() &&
{
check_has_value();
return value_;
}
const T&& value() const&&
{
check_has_value();
return value_;
}

// https://en.cppreference.com/w/cpp/utility/optional/operator*
const T* operator->() const
{
assert(has_value());
return &value_; // "This operator does not check whether the optional contains a value!"
}
T* operator->() noexcept
{
assert(has_value());
return &value_; // "This operator does not check whether the optional contains a value!"
}

const T& operator*() const&
{
assert(has_value());
return value_; // "This operator does not check whether the optional contains a value!"
}
T& operator*() &
{
assert(has_value());
return value_; // "This operator does not check whether the optional contains a value!"
}
const T&& operator*() const&&
{
assert(has_value());
return value_; // "This operator does not check whether the optional contains a value!"
}
T&& operator*() &&
{
assert(has_value());
return value_; // "This operator does not check whether the optional contains a value!"
}

// https://en.cppreference.com/w/cpp/utility/optional/value_or
template<typename U>
T value_or(U&& default_value) const&
{
// Equivalent to bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value))
return has_value() ? **this : static_cast<T>(std::forward<U>(default_value));
}
template <typename U>
T value_or(U&& default_value) &&
{
// Equivalent to bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(default_value))
return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(default_value));
}
};

template<typename T>
using optional = details::optional<T>;

// https://en.cppreference.com/w/cpp/utility/optional/make_optional
template <typename T, typename... TArgs>
inline optional<T> make_optional(TArgs&&... args)
{
return optional<T>(T(std::forward<TArgs>(args)...));
}

// https://en.cppreference.com/w/cpp/utility/optional/operator_cmp
// Compares two optional objects, lhs and rhs. The contained values are compared
// (using the corresponding operator of T) only if both lhs and rhs contain values. Otherwise,
// * lhs is considered equal to rhs if, and only if, both lhs and rhs do not contain a value.
// * lhs is considered less than rhs if, and only if, rhs contains a value and lhs does not.
template <typename T, typename U>
inline bool operator==(const optional<T>& lhs, const optional<U>& rhs)
{
// If bool(lhs) != bool(rhs), returns false
if (bool(lhs) != bool(rhs))
{
return false;
}
// Otherwise, if bool(lhs) == false (and so bool(rhs) == false as well), returns true
if (!lhs.has_value())
{
assert(!rhs.has_value());
return true;
}
// Otherwise, returns *lhs == *rhs.
return *lhs == *rhs;
}
template <typename T, typename U>
inline bool operator==(const T& value, const optional<U>& opt)
{
return make_optional<T>(value) == opt;
}
template <typename T, typename U>
inline bool operator==(const optional<T>& opt, const U& value)
{
return opt == make_optional<U>(value);
}

template <typename T, typename U>
inline bool operator!=(const optional<T>& lhs, const optional<U>& rhs)
{
return !(lhs == rhs);
}
template <typename T, typename U>
inline bool operator!=(const T& value, const optional<U>& opt)
{
return !(value == opt);
}
template <typename T, typename U>
inline bool operator!=(const optional<T>& opt, const U& value)
{
return !(opt == value);
}

template <typename T, typename U>
inline bool operator<(const optional<T>& lhs, const optional<U>& rhs)
{
// If bool(rhs) == false returns false
if (!rhs.has_value())
{
return false;
}
// Otherwise, if bool(lhs) == false, returns true
if (!lhs.has_value())
{
return true;
}
// Otherwise returns *lhs < *rhs
return *lhs < *rhs;
}
template <typename T, typename U>
inline bool operator<(const T& value, const optional<U>& opt)
{
return make_optional<T>(value) < opt;
}
template <typename T, typename U>
inline bool operator<(const optional<T>& opt, const U& value)
{
return opt < make_optional<U>(value);
}

template <typename T, typename U>
inline bool operator<=(const optional<T>& lhs, const optional<U>& rhs)
{
// If bool(lhs) == false returns true
if (!lhs.has_value())
{
return true;
}
// Otherwise, if bool(rhs) == false, returns false
if (!rhs.has_value())
{
return false;
}
// Otherwise returns *lhs <= *rhs
return *lhs <= *rhs;
}
template <typename T, typename U>
inline bool operator<=(const T& value, const optional<U>& opt)
{
return make_optional<T>(value) <= opt;
}
template <typename T, typename U>
inline bool operator<=(const optional<T>& opt, const U& value)
{
return opt <= make_optional<U>(value);
}

template <typename T, typename U>
inline bool operator>(const optional<T>& lhs, const optional<U>& rhs)
{
// If bool(lhs) == false returns false
if (!lhs.has_value())
{
return false;
}
// Otherwise, if bool(rhs) == false, returns true
if (!rhs.has_value())
{
return true;
}
// Otherwise returns *lhs > *rhs
return *lhs > *rhs;
}
template <typename T, typename U>
inline bool operator>(const T& value, const optional<U>& opt)
{
return make_optional<T>(value) > opt;
}
template <typename T, typename U>
inline bool operator>(const optional<T>& opt, const U& value)
{
return opt > make_optional<U>(value);
}

template <typename T, typename U>
inline bool operator>=(const optional<T>& lhs, const optional<U>& rhs)
{
// If bool(rhs) == false returns true
if (!rhs.has_value())
{
return true;
}
// Otherwise, if bool(lhs) == false, returns false
if (!lhs.has_value())
{
return false;
}
// Otherwise returns *lhs >= *rhs
return *lhs >= *rhs;
}
template <typename T, typename U>
inline bool operator>=(const T& value, const optional<U>& opt)
{
return make_optional<T>(value) >= opt;
}
template <typename T, typename U>
inline bool operator>=(const optional<T>& opt, const U& value)
{
return opt >= make_optional<U>(value);
return details::make_optional<T>(std::forward<TArgs>(args)...);
}
}

Expand Down
Loading

0 comments on commit d81a4d1

Please sign in to comment.