Skip to content

Commit

Permalink
Improvements to the poor_mans_optional class:
Browse files Browse the repository at this point in the history
* `operator*` to enable `my_optional->some_method()`
* Added `constexpr` for a bunch of methods - and made it conditional on a simple trait-based condition in some of them
* Default initializer for the maybe-value union
* Added `nullopt` support
  • Loading branch information
eyalroz committed Mar 13, 2023
1 parent cda2340 commit 3d33499
Showing 1 changed file with 30 additions and 15 deletions.
45 changes: 30 additions & 15 deletions src/cuda/api/detail/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#ifndef CUDA_API_WRAPPERS_OPTIONAL_HPP
#define CUDA_API_WRAPPERS_OPTIONAL_HPP

#include <type_traits>

#if __cplusplus >= 201703L
#include <optional>
#include <any>
Expand All @@ -28,10 +30,18 @@ using ::std::experimental::nullopt;

namespace cuda {


namespace detail_ {

struct no_value_t { };

} // namespace detail_

using nullopt_t = detail_::no_value_t;
constexpr nullopt_t nullopt{};

namespace detail_ {

template<typename T>
struct poor_mans_optional {
static_assert(::std::is_trivially_destructible<T>::value, "Use a simpler type");
Expand All @@ -40,18 +50,18 @@ struct poor_mans_optional {
T value;
};

poor_mans_optional &operator=(const poor_mans_optional &other) = default;
poor_mans_optional &operator=(const poor_mans_optional &other) noexcept = default;

poor_mans_optional &operator=(poor_mans_optional &&other) = default;
poor_mans_optional &operator=(poor_mans_optional &&other) noexcept = default;

poor_mans_optional &operator=(const T &value)
poor_mans_optional &operator=(const T &value) noexcept(std::is_nothrow_assignable<T,T>::value)
{
has_value_ = true;
maybe_value.value = value;
return *this;
}

poor_mans_optional &operator=(const T &&value)
poor_mans_optional &operator=(const T &&value) noexcept(std::is_nothrow_move_assignable<T>::value)
{
has_value_ = true;
maybe_value.value = ::std::move(value);
Expand All @@ -64,30 +74,37 @@ struct poor_mans_optional {
return *this;
}

poor_mans_optional &operator=(T &&value)
poor_mans_optional &operator=(T &&value) noexcept(std::is_nothrow_move_assignable<T>::value)
{ return *this = value; }

poor_mans_optional() noexcept: has_value_(false), maybe_value{no_value_t{}}
poor_mans_optional() noexcept: has_value_(false)
{}

poor_mans_optional(T v) : has_value_(true)
poor_mans_optional(T v) noexcept(std::is_nothrow_assignable<T,T>::value) : has_value_(true)
{
maybe_value.value = v;
}

poor_mans_optional(const poor_mans_optional &other)
poor_mans_optional(const poor_mans_optional &other) noexcept
: has_value_(other.has_value_), maybe_value(other.maybe_value)
{ }

poor_mans_optional(poor_mans_optional &&other) noexcept
: has_value_(other.has_value_), maybe_value(other.maybe_value)
{
if (other) {
*this = other.value();
}
has_value_ = other.has_value_;
other.has_value_ = false;
}

poor_mans_optional(nullopt_t) noexcept : has_value_(false) { }

~poor_mans_optional() noexcept = default;

T value() const
{ return maybe_value.value; }

T& operator*() noexcept { return maybe_value.value; }
const T& operator*() const noexcept { return maybe_value.value; }

operator bool() const noexcept
{ return has_value_; }

Expand All @@ -99,15 +116,13 @@ struct poor_mans_optional {

protected:
bool has_value_;
maybe_value_union_t maybe_value;
maybe_value_union_t maybe_value { no_value_t{} };
};

} // namespace detail_

template<typename T>
using optional = cuda::detail_::poor_mans_optional<T>;
using nullopt_t = detail_::no_value_t;
constexpr nullopt_t nullopt{};

} // namespace cuda

Expand Down

0 comments on commit 3d33499

Please sign in to comment.