srsLTE/lib/include/srsran/adt/optional.h

150 lines
3.7 KiB
C++

/**
* Copyright 2013-2022 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSRAN_OPTIONAL_H
#define SRSRAN_OPTIONAL_H
#include "detail/type_storage.h"
#include "srsran/support/srsran_assert.h"
namespace srsran {
template <typename T>
class optional
{
public:
using value_type = T;
optional() : has_val_(false), empty() {}
optional(const T& t) : has_val_(true) { storage.emplace(t); }
optional(T&& t) : has_val_(true) { storage.emplace(std::move(t)); }
optional(const optional<T>& other) : has_val_(other.has_value())
{
if (other.has_value()) {
storage.copy_ctor(other.storage);
}
}
optional(optional<T>&& other) noexcept : has_val_(other.has_value())
{
if (other.has_value()) {
storage.move_ctor(std::move(other.storage));
}
}
optional& operator=(const optional<T>& other)
{
if (this == &other) {
return *this;
}
copy_if_present_helper(storage, other.storage, has_value(), other.has_value());
has_val_ = other.has_value();
return *this;
}
optional& operator=(optional<T>&& other) noexcept
{
move_if_present_helper(storage, other.storage, has_value(), other.has_value());
has_val_ = other.has_value();
return *this;
}
~optional()
{
if (has_value()) {
storage.destroy();
}
}
bool has_value() const { return has_val_; }
explicit operator bool() const { return has_value(); }
T* operator->() { return &value(); }
const T* operator->() const { return &value(); }
T& operator*() { return value(); }
const T& operator*() const { return value(); }
T& value()
{
srsran_assert(has_val_, "Invalid optional<T> access");
return storage.get();
}
const T& value() const
{
srsran_assert(has_val_, "Invalid optional<T> access");
return storage.get();
}
template <typename... Args>
void emplace(Args&&... args)
{
if (has_value()) {
storage.destroy();
}
storage.emplace(std::forward<Args>(args)...);
has_val_ = true;
}
void reset()
{
if (has_value()) {
storage.destroy();
has_val_ = false;
}
}
private:
bool has_val_;
union {
char empty;
detail::type_storage<T> storage;
};
};
template <typename T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs)
{
return lhs.has_value() == rhs.has_value() and (not lhs.has_value() or lhs.value() == rhs.value());
}
template <typename T>
bool operator==(const optional<T>& lhs, const T& rhs)
{
return lhs.has_value() and lhs.value() == rhs;
}
template <typename T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs)
{
return not(lhs == rhs);
}
template <typename T>
bool operator!=(const optional<T>& lhs, const T& rhs)
{
return not(lhs == rhs);
}
template <typename T>
bool operator<(const optional<T>& lhs, const optional<T>& rhs)
{
return rhs.has_value() and ((lhs.has_value() and lhs.value() < rhs.value()) or (not lhs.has_value()));
}
} // namespace srsran
#endif // SRSRAN_OPTIONAL_H