Skip to content

use optional return types for fallible methods - #152

Open
redraincatching wants to merge 1 commit into
bemanproject:mainfrom
redraincatching:return-types
Open

redraincatching wants to merge 1 commit into
bemanproject:mainfrom
redraincatching:return-types

Conversation

@redraincatching

Copy link
Copy Markdown

closes #119 by implementing p3981, using beman.optional as specified in the issue.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

pre-commit

[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

template <typename Pointer, typename IteratorConcept>
struct pointer {
using type = Pointer;


[pre-commit] reported by reviewdog 🐶

template <typename Pointer>
struct pointer<Pointer, std::output_iterator_tag> {
using type = void;


[pre-commit] reported by reviewdog 🐶

std::integral_constant<bool, (std::is_convertible<T, U>::value || std::is_convertible<U, T>::value)>;


[pre-commit] reported by reviewdog 🐶

using use_base = decltype(access::base(std::declval<T&>()));


[pre-commit] reported by reviewdog 🐶

template <typename... T>
using void_t = void;


[pre-commit] reported by reviewdog 🐶

template <typename AlwaysVoid, template <class...> class Template, typename... Args>


[pre-commit] reported by reviewdog 🐶

struct detector<void_t<Template<Args...>>, Template, Args...> : std::true_type {};


[pre-commit] reported by reviewdog 🐶

template <typename T, typename U, bool UseBase = detector<void, use_base, T>::value>


[pre-commit] reported by reviewdog 🐶

static constexpr auto call(T lhs, U rhs) {
return static_cast<common_t<T, U>>(lhs).derived() == static_cast<common_t<T, U>>(rhs).derived();
}


[pre-commit] reported by reviewdog 🐶

template <typename T, typename U>
struct common_eq<T, U, true> {
static constexpr auto call(T lhs, U rhs) { return access::base(lhs) == access::base(rhs); }


[pre-commit] reported by reviewdog 🐶

common_diff(T lhs, U rhs) noexcept(noexcept(static_cast<common_t<T, U>>(lhs) - static_cast<common_t<T, U>>(rhs)))
-> decltype(static_cast<common_t<T, U>>(lhs) - static_cast<common_t<T, U>>(rhs)) {
return static_cast<common_t<T, U>>(lhs) - static_cast<common_t<T, U>>(rhs);


[pre-commit] reported by reviewdog 🐶

/** A CRTP template that one may derive from to make defining iterators
easier.
The template parameter `D` for `iterator_interface` may be an
incomplete type. Before any member of the resulting specialization of
`iterator_interface` other than special member functions is
referenced, `D` shall be complete, and model
`std::derived_from<iterator_interface<D>>`. */
template <typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference = ValueType&,
typename Pointer = ValueType*,
typename DifferenceType = std::ptrdiff_t


[pre-commit] reported by reviewdog 🐶

,
typename E = std::enable_if_t<std::is_class<Derived>::value &&
std::is_same<Derived, std::remove_cv_t<Derived>>::value>


[pre-commit] reported by reviewdog 🐶

>
struct iterator_interface;
namespace v1_dtl {
template <typename Iterator, typename = void>
struct ra_iter : std::false_type {};
template <typename Iterator>
struct ra_iter<Iterator, void_t<typename Iterator::iterator_concept>>
: std::integral_constant<
bool,
std::is_base_of<std::random_access_iterator_tag, typename Iterator::iterator_concept>::value> {};
template <typename Iterator, typename DifferenceType, typename = void>
struct plus_eq : std::false_type {};
template <typename Iterator, typename DifferenceType>
struct plus_eq<Iterator,
DifferenceType,
void_t<decltype(std::declval<Iterator&>() += std::declval<DifferenceType>())>> : std::true_type {};
template <typename D,
typename IteratorConcept,
typename ValueType,
typename Reference,
typename Pointer,
typename DifferenceType>
void
derived_iterator(const iterator_interface<D, IteratorConcept, ValueType, Reference, Pointer, DifferenceType>&);
} // namespace v1_dtl
template <typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference,
typename Pointer,
typename DifferenceType


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

private:
constexpr Derived& derived() noexcept { return static_cast<Derived&>(*this); }
constexpr const Derived& derived() const noexcept { return static_cast<const Derived&>(*this); }


[pre-commit] reported by reviewdog 🐶

template <typename T, typename U, bool UseBase>
friend struct detail::common_eq;


[pre-commit] reported by reviewdog 🐶

public:
using iterator_concept = IteratorConcept;
using iterator_category = iterator_concept;
using value_type = std::remove_const_t<ValueType>;
using reference = Reference;
using pointer = detail::pointer_t<Pointer, iterator_concept>;
using difference_type = DifferenceType;
template <typename D = Derived>
constexpr auto operator*() noexcept(noexcept(*access::base(std::declval<D&>())))
-> decltype(*access::base(std::declval<D&>())) {
return *access::base(derived());
}
template <typename D = Derived>
constexpr auto operator*() const noexcept(noexcept(*access::base(std::declval<const D&>())))
-> decltype(*access::base(std::declval<const D&>())) {
return *access::base(derived());
}
template <typename D = Derived>
constexpr auto operator->() noexcept(noexcept(detail::make_pointer<pointer, reference>(*std::declval<D&>())))
-> decltype(detail::make_pointer<pointer, reference>(*std::declval<D&>())) {
return detail::make_pointer<pointer, reference>(*derived());
}
template <typename D = Derived>
constexpr auto operator->() const
noexcept(noexcept(detail::make_pointer<pointer, reference>(*std::declval<const D&>())))
-> decltype(detail::make_pointer<pointer, reference>(*std::declval<const D&>())) {
return detail::make_pointer<pointer, reference>(*derived());
}
template <typename D = Derived>
constexpr auto operator[](difference_type i) const
noexcept(noexcept(D(std::declval<const D&>()), std::declval<D&>() += i, *std::declval<D&>()))
-> decltype(std::declval<D&>() += i, *std::declval<D&>()) {
D retval = derived();
retval += i;
return *retval;
}
template <typename D = Derived,
typename Enable = std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
constexpr auto operator++() noexcept(noexcept(++access::base(std::declval<D&>())))
-> decltype(++access::base(std::declval<D&>()), std::declval<D&>()) {
++access::base(derived());
return derived();
}
template <typename D = Derived>
constexpr auto operator++() noexcept(noexcept(std::declval<D&>() += difference_type(1)))
-> decltype(std::declval<D&>() += difference_type(1), std::declval<D&>()) {
derived() += difference_type(1);
return derived();
}
template <typename D = Derived>
constexpr auto operator++(int) noexcept(noexcept(D(std::declval<D&>()), ++std::declval<D&>()))
-> std::remove_reference_t<decltype(D(std::declval<D&>()), ++std::declval<D&>(), std::declval<D&>())> {
D retval = derived();
++derived();
return retval;
}
template <typename D = Derived>
constexpr auto operator+=(difference_type n) noexcept(noexcept(access::base(std::declval<D&>()) += n))
-> decltype(access::base(std::declval<D&>()) += n, std::declval<D&>()) {
access::base(derived()) += n;
return derived();
}
template <typename D = Derived>
constexpr auto operator+(difference_type i) const noexcept(noexcept(D(std::declval<D&>()),
std::declval<D&>() += i))
-> std::remove_reference_t<decltype(D(std::declval<D&>()), std::declval<D&>() += i, std::declval<D&>())> {
D retval = derived();
retval += i;
return retval;
}
friend BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived operator+(difference_type i,
Derived it) noexcept {
return it + i;
}
template <typename D = Derived,
typename Enable = std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
constexpr auto operator--() noexcept(noexcept(--access::base(std::declval<D&>())))
-> decltype(--access::base(std::declval<D&>()), std::declval<D&>()) {
--access::base(derived());
return derived();
}
template <typename D = Derived>
constexpr auto operator--() noexcept(noexcept(D(std::declval<D&>()),
std::declval<D&>() += -difference_type(1)))
-> decltype(std::declval<D&>() += -difference_type(1), std::declval<D&>()) {
derived() += -difference_type(1);
return derived();
}
template <typename D = Derived>
constexpr auto operator--(int) noexcept(noexcept(D(std::declval<D&>()), --std::declval<D&>()))
-> std::remove_reference_t<decltype(D(std::declval<D&>()), --std::declval<D&>(), std::declval<D&>())> {
D retval = derived();
--derived();
return retval;
}


[pre-commit] reported by reviewdog 🐶

template <typename D = Derived>
constexpr D& operator-=(difference_type i) noexcept {
derived() += -i;
return derived();
}


[pre-commit] reported by reviewdog 🐶

template <typename D = Derived>
constexpr auto operator-(D other) const
noexcept(noexcept(access::base(std::declval<const D&>()) - access::base(other)))
-> decltype(access::base(std::declval<const D&>()) - access::base(other)) {
return access::base(derived()) - access::base(other);
}


[pre-commit] reported by reviewdog 🐶

friend BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
operator-(Derived it, difference_type i) noexcept {
Derived retval = it;
retval += -i;
return retval;
}
};


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator==()`, implemented in terms of the iterator
underlying IteratorInterface, for all iterators derived from
`iterator_interface`, except those with an iterator category derived
from `std::random_access_iterator_tag`. */
template <typename IteratorInterface1,
typename IteratorInterface2,
typename Enable = std::enable_if_t<!v1_dtl::ra_iter<IteratorInterface1>::value>>
constexpr auto operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept
-> decltype(access::base(std::declval<IteratorInterface1&>()) ==
access::base(std::declval<IteratorInterface2&>())) {
return access::base(lhs) == access::base(rhs);


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator==()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template <typename IteratorInterface1,
typename IteratorInterface2,
typename Enable = std::enable_if_t<v1_dtl::ra_iter<IteratorInterface1>::value>>
constexpr auto operator==(IteratorInterface1 lhs,
IteratorInterface2 rhs) noexcept(noexcept(detail::common_diff(lhs, rhs)))
->decltype(v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) == 0) {
return detail::common_diff(lhs, rhs) == 0;


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator!=()` for all iterators derived from
`iterator_interface`. */
template <typename IteratorInterface1, typename IteratorInterface2>
constexpr auto operator!=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(noexcept(!(lhs == rhs)))
->decltype(v1_dtl::derived_iterator(lhs), !(lhs == rhs)) {
return !(lhs == rhs);


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator<()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template <typename IteratorInterface1, typename IteratorInterface2>
constexpr auto operator<(IteratorInterface1 lhs,
IteratorInterface2 rhs) noexcept(noexcept(detail::common_diff(lhs, rhs)))
->decltype(v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) < 0) {
return detail::common_diff(lhs, rhs) < 0;


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator<=()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template <typename IteratorInterface1, typename IteratorInterface2>
constexpr auto operator<=(IteratorInterface1 lhs,
IteratorInterface2 rhs) noexcept(noexcept(detail::common_diff(lhs, rhs)))
->decltype(v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) <= 0) {
return detail::common_diff(lhs, rhs) <= 0;


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator>()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template <typename IteratorInterface1, typename IteratorInterface2>
constexpr auto operator>(IteratorInterface1 lhs,
IteratorInterface2 rhs) noexcept(noexcept(detail::common_diff(lhs, rhs)))
->decltype(v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) > 0) {
return detail::common_diff(lhs, rhs) > 0;


[pre-commit] reported by reviewdog 🐶

/** Implementation of `operator>=()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template <typename IteratorInterface1, typename IteratorInterface2>
constexpr auto operator>=(IteratorInterface1 lhs,
IteratorInterface2 rhs) noexcept(noexcept(detail::common_diff(lhs, rhs)))
->decltype(v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) >= 0) {
return detail::common_diff(lhs, rhs) >= 0;


[pre-commit] reported by reviewdog 🐶

/** A template alias useful for defining proxy iterators. \see
`iterator_interface`. */
template <typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference = ValueType,
typename DifferenceType = std::ptrdiff_t>
using proxy_iterator_interface = iterator_interface<Derived,
IteratorConcept,
ValueType,
Reference,
proxy_arrow_result<Reference>,
DifferenceType>;


[pre-commit] reported by reviewdog 🐶

#if defined(BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_DOXYGEN) || BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_USE_CONCEPTS


[pre-commit] reported by reviewdog 🐶

namespace v2_dtl {
template <typename Iterator>
struct iter_concept;
template <typename Iterator>
requires requires { typename std::iterator_traits<Iterator>::iterator_concept; }
struct iter_concept<Iterator> {
using type = typename std::iterator_traits<Iterator>::iterator_concept;
};
template <typename Iterator>
requires (
!requires { typename std::iterator_traits<Iterator>::iterator_concept; } &&
requires { typename std::iterator_traits<Iterator>::iterator_category; })
struct iter_concept<Iterator> {
using type = typename std::iterator_traits<Iterator>::iterator_category;
};
template <typename Iterator>
requires (
!requires { typename std::iterator_traits<Iterator>::iterator_concept; } &&
!requires { typename std::iterator_traits<Iterator>::iterator_category; })
struct iter_concept<Iterator> {
using type = std::random_access_iterator_tag;
};
template <typename Iterator>
struct iter_concept {};
template <typename Iterator>
using iter_concept_t = typename iter_concept<Iterator>::type;


[pre-commit] reported by reviewdog 🐶

template <typename D, typename DifferenceType>
// clang-format off


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

template <typename D, typename D2 = D>
// clang-format off


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

template <typename D1, typename D2 = D1>
// clang-format off


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

template <typename D, typename D2 = D>
// clang-format off


[pre-commit] reported by reviewdog 🐶

// clang-format on
// This iterator concept -> category mapping scheme follows the one
// from zip_transform_view; see
// https://eel.is/c++draft/range.zip.transform.iterator#1.
template <typename IteratorConcept, typename ReferenceType>
constexpr auto category_tag() {
if constexpr (std::is_base_of_v<std::forward_iterator_tag, IteratorConcept>) {
if constexpr (!std::is_reference_v<ReferenceType>) {
return std::input_iterator_tag{};
} else if constexpr (std::is_base_of_v<std::random_access_iterator_tag, IteratorConcept>) {
return std::random_access_iterator_tag{};
} else if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, IteratorConcept>) {
return std::bidirectional_iterator_tag{};
} else {
return std::forward_iterator_tag{};
}
} else {
return 0; // int means "no tag"
}
}
template <typename IteratorConcept,
typename ReferenceType,
typename IteratorCategory = decltype(v2_dtl::category_tag<IteratorConcept, ReferenceType>())>
struct iterator_category_base {
using iterator_category = IteratorCategory;
};
template <typename IteratorConcept, typename ReferenceType>
struct iterator_category_base<IteratorConcept, ReferenceType, int> {};
template <typename IteratorConcept, typename ReferenceType>
constexpr bool non_input_tag() {
if (std::same_as<IteratorConcept, std::input_iterator_tag>)
return false;
using tag_t = decltype(v2_dtl::category_tag<IteratorConcept, ReferenceType>());
return !std::same_as<tag_t, std::input_iterator_tag>;


[pre-commit] reported by reviewdog 🐶

} // namespace v2_dtl
// clang-format off


[pre-commit] reported by reviewdog 🐶

// clang-format on
/** A template alias useful for defining proxy iterators. \see
`iterator_interface`. */
template <typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference = ValueType,
typename DifferenceType = std::ptrdiff_t>
using proxy_iterator_interface = iterator_interface<Derived,
IteratorConcept,
ValueType,
Reference,
proxy_arrow_result<Reference>,
DifferenceType>;


[pre-commit] reported by reviewdog 🐶

#if defined(BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_DOXYGEN) || BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_USE_DEDUCED_THIS


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

/** A template alias useful for defining proxy iterators. \see
`iterator_interface`. */
template <typename IteratorConcept,
typename ValueType,
typename Reference = ValueType,
typename DifferenceType = std::ptrdiff_t>
using proxy_iterator_interface =
iterator_interface<IteratorConcept, ValueType, Reference, proxy_arrow_result<Reference>, DifferenceType>;


[pre-commit] reported by reviewdog 🐶

For example: `BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_CONCEPT(my_iter,


[pre-commit] reported by reviewdog 🐶

#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name)


[pre-commit] reported by reviewdog 🐶

For example: `BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(my_iter,
std::input_iterator_tag, std::input_iterator, int, int &, int *, std::ptrdiff_t)`.


[pre-commit] reported by reviewdog 🐶

#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \


[pre-commit] reported by reviewdog 🐶

#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL(type, concept_name) \
static_assert(concept_name<type>, "");


[pre-commit] reported by reviewdog 🐶

#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name) \
BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL(iter, concept_name)


[pre-commit] reported by reviewdog 🐶

#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name)


[pre-commit] reported by reviewdog 🐶

#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
iter, category, value_t, ref, ptr, diff_t) \
static_assert(std::is_same<typename std::iterator_traits<iter>::value_type, value_t>::value, ""); \
static_assert(std::is_same<typename std::iterator_traits<iter>::reference, ref>::value, ""); \
static_assert(std::is_same<typename std::iterator_traits<iter>::pointer, ptr>::value, ""); \
static_assert(std::is_same<typename std::iterator_traits<iter>::difference_type, diff_t>::value, "");
#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
iter, category, concept, value_type, reference, pointer, difference_type) \
BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
iter, category, value_type, reference, pointer, difference_type)


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

#if defined(__cpp_lib_format_ranges)


[pre-commit] reported by reviewdog 🐶

concept optional_eq_rel = requires(const T& t, const U& u) {
{ t == u } -> std::convertible_to<bool>;


[pre-commit] reported by reviewdog 🐶

concept optional_ne_rel = requires(const T& t, const U& u) {
{ t != u } -> std::convertible_to<bool>;


[pre-commit] reported by reviewdog 🐶

concept optional_lt_rel = requires(const T& t, const U& u) {
{ t < u } -> std::convertible_to<bool>;


[pre-commit] reported by reviewdog 🐶

concept optional_gt_rel = requires(const T& t, const U& u) {
{ t > u } -> std::convertible_to<bool>;


[pre-commit] reported by reviewdog 🐶

concept optional_le_rel = requires(const T& t, const U& u) {
{ t <= u } -> std::convertible_to<bool>;


[pre-commit] reported by reviewdog 🐶

concept optional_ge_rel = requires(const T& t, const U& u) {
{ t >= u } -> std::convertible_to<bool>;


[pre-commit] reported by reviewdog 🐶

explicit from_function_t() = default;


[pre-commit] reported by reviewdog 🐶

explicit in_place_t() = default;


[pre-commit] reported by reviewdog 🐶

template <class T>
class optional; // partially freestanding


[pre-commit] reported by reviewdog 🐶

inline constexpr bool std::ranges::enable_view<beman::optional::optional<T>> = true;


[pre-commit] reported by reviewdog 🐶

inline constexpr bool std::ranges::enable_borrowed_range<beman::optional::optional<T&>> = true;


[pre-commit] reported by reviewdog 🐶

inline constexpr auto std::format_kind<beman::optional::optional<T>> = range_format::disabled;


[pre-commit] reported by reviewdog 🐶

template <typename T>
inline constexpr bool is_optional = false;
template <typename T>
inline constexpr bool is_optional<optional<T>> = true;


[pre-commit] reported by reviewdog 🐶

concept is_derived_from_optional = requires(const T& t) { // exposition only
[]<class U>(const optional<U>&) {}(t);


[pre-commit] reported by reviewdog 🐶

/** @enum Tag
* @brief Tag enum for nullopt_t construction
*/
enum class Tag { tag /**< the tag value for nullopt_t::Tag */ };
/**
* @brief Construct a new nullopt_t object
* @arg Tag
* @details constexpr for nullopt_t to be literal.
*/
explicit constexpr nullopt_t(Tag) noexcept {}
private:
friend constexpr bool operator==(nullopt_t, nullopt_t) noexcept { return true; }
friend constexpr std::strong_ordering operator<=>(nullopt_t, nullopt_t) noexcept {
return std::strong_ordering::equivalent;
}


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_eq_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_ne_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_lt_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_gt_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_le_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_ge_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr std::compare_three_way_result_t<T, U> operator<=>(const optional<T>&, const optional<U>&);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;


[pre-commit] reported by reviewdog 🐶

constexpr std::strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_eq_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_eq_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator!=(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_ne_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator!=(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_ne_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_lt_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_lt_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_gt_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_gt_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<=(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_le_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<=(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_le_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>=(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_ge_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>=(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_ge_rel<T, U>;


[pre-commit] reported by reviewdog 🐶

requires (!is_derived_from_optional<U>) && std::three_way_comparable_with<T, U>
constexpr std::compare_three_way_result_t<T, U> operator<=>(const optional<T>& x, const U& v);


[pre-commit] reported by reviewdog 🐶

constexpr void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
requires std::is_move_constructible_v<T> && std::is_swappable_v<T>;


[pre-commit] reported by reviewdog 🐶

constexpr optional<std::decay_t<T>>
make_optional(T&&) noexcept(std::is_nothrow_constructible_v<optional<std::decay_t<T>>, T>)
requires std::is_constructible_v<std::decay_t<T>, T>;


[pre-commit] reported by reviewdog 🐶

constexpr optional<T> make_optional(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
requires std::is_constructible_v<T, Args...>;


[pre-commit] reported by reviewdog 🐶

make_optional(std::initializer_list<U> il,
Args&&... args) noexcept(std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
requires std::is_constructible_v<T, std::initializer_list<U>&, Args...>;


[pre-commit] reported by reviewdog 🐶

!std::is_same_v<std::decay_t<U>, in_place_t> && std::is_constructible_v<T, U&&>;


[pre-commit] reported by reviewdog 🐶

concept enable_from_other = !std::is_same_v<T, U> && //
std::is_constructible_v<T, Other> && //
!std::is_constructible_v<T, optional<U>&> && //
!std::is_constructible_v<T, optional<U>&&> && //
!std::is_constructible_v<T, const optional<U>&> && //
!std::is_constructible_v<T, const optional<U>&&> && //
!std::is_convertible_v<optional<U>&, T> && //
!std::is_convertible_v<optional<U>&&, T> && //
!std::is_convertible_v<const optional<U>&, T> && //
!std::is_convertible_v<const optional<U>&&, T>;


[pre-commit] reported by reviewdog 🐶

concept enable_assign_forward = !std::is_same_v<optional<T>, std::decay_t<U>> &&
!std::conjunction_v<std::is_scalar<T>, std::is_same<T, std::decay_t<U>>> &&
std::is_constructible_v<T, U> && std::is_assignable_v<T&, U>;


[pre-commit] reported by reviewdog 🐶

std::is_constructible_v<T, Other> && std::is_assignable_v<T&, Other> &&
!std::is_constructible_v<T, optional<U>&> && !std::is_constructible_v<T, optional<U>&&> &&
!std::is_constructible_v<T, const optional<U>&> && !std::is_constructible_v<T, const optional<U>&&> &&
!std::is_convertible_v<optional<U>&, T> && !std::is_convertible_v<optional<U>&&, T> &&
!std::is_convertible_v<const optional<U>&, T> && !std::is_convertible_v<const optional<U>&&, T> &&
!std::is_assignable_v<T&, optional<U>&> && !std::is_assignable_v<T&, optional<U>&&> &&
!std::is_assignable_v<T&, const optional<U>&> && !std::is_assignable_v<T&, const optional<U>&&>;


[pre-commit] reported by reviewdog 🐶

template <class T>
class optional {
static_assert((!std::is_same_v<T, std::remove_cv_t<in_place_t>>) &&
(!std::is_same_v<std::remove_cv_t<T>, nullopt_t>));
static_assert(std::is_object_v<T> && !std::is_array_v<T>);
public:
/**
* @brief Type alias for the value type contained in the optional.
*
*/
using value_type = T;
/**
* @brief Type alias for the iterator type of the optional.
*
* @details Since P3168R2: Give std::optional Range Support.
*/
using iterator = detail::contiguous_iterator<T,
optional>; // see~\ref{optional.iterators}
/**
* @brief Type alias for the const iterator type of the optional.
*
* @details Since P3168R2: Give std::optional Range Support.
*/
using const_iterator = detail::contiguous_iterator<const T,
optional>; // see~\ref{optional.iterators}
// \ref{optional.ctor}, constructors
/**
* @brief Default constructs an empty optional.
*
*/
constexpr optional() noexcept;
/**
* @brief Constructs an empty optional.
*
*/
constexpr optional(nullopt_t) noexcept;
/**
* @brief Copy constructs the value from \p rhs if it has one.
*
*/
constexpr optional(const optional& rhs)
requires std::is_copy_constructible_v<T> && (!std::is_trivially_copy_constructible_v<T>);
/**
* @brief Copy constructs the value from \p rhs if it has one.
* @details Defaulted if T is trivially copy constructible.
*/
constexpr optional(const optional&)
requires std::is_copy_constructible_v<T> && std::is_trivially_copy_constructible_v<T>
= default;
/**
* @brief Move constructs the value from \p rhs if it has one.
*/
constexpr optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
requires std::is_move_constructible_v<T> && (!std::is_trivially_move_constructible_v<T>);
/**
* @brief Move constructs the value from \p rhs if it has one.
* @details Defaulted if T is trivially move constructible.
*/
constexpr optional(optional&&)
requires std::is_move_constructible_v<T> && std::is_trivially_move_constructible_v<T>
= default;
/**
* @brief Constructs the value in-place using the given arguments.
*
* @param args The arguments to use for in-place construction.
*/
template <class... Args>
constexpr explicit optional(in_place_t, Args&&... args)
requires std::is_constructible_v<T, Args...>;
/**
* @brief Constructs the value in-place using the given arguments.
*
* @param il The initializer list to use for in-place construction.
* @param args The arguments to use for in-place construction.
*/
template <class U, class... Args>
constexpr explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
requires std::is_constructible_v<T, std::initializer_list<U>&, Args&&...>;
/**
* @brief Constructs the value from \p u, forwarding it if necessary.
*
* If \p u is convertible to \p T, this is an explicit constructor.
*/
template <class U = T>
constexpr explicit(!std::is_convertible_v<U, T>) optional(U&& u)
requires detail::enable_forward_value<T, U>;
/**
* @brief Constructs the value from \p rhs if it has one.
*
* @tparam U
*/
template <class U>
constexpr explicit(!std::is_convertible_v<U, T>) optional(const optional<U>& rhs)
requires (detail::enable_from_other<T, U, const U&>);
/**
* @brief Constructs the value from \p rhs if it has one.
*/
template <class U>
constexpr explicit(!std::is_convertible_v<U, T>) optional(optional<U>&& rhs)
requires (detail::enable_from_other<T, U, U &&>);
// \ref{optional.dtor}, destructor
/**
* @brief Destructs the optional.
*
*/
constexpr ~optional()
requires std::is_trivially_destructible_v<T>
= default;
/**
* @brief Destroys the optional and its value if it has one.
*/
constexpr ~optional()
requires (!std::is_trivially_destructible_v<T>);
// \ref{optional.assign}, assignment
/**
* @brief Resets the optional to an empty state.
*/
constexpr optional& operator=(nullopt_t) noexcept;
/**
* @brief Copy assigns the value from \p rhs if it has one.
*/
constexpr optional& operator=(const optional& rhs)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
(!std::is_trivially_copy_assignable_v<T>);
/**
* @brief Copy assigns the value from \p rhs if it has one.
*
* @return optional&
*/
constexpr optional& operator=(const optional&)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>
= default;
/**
* @brief Move assigns the value from \p rhs if it has one.
*/
constexpr optional& operator=(optional&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
requires std::is_move_constructible_v<T> && std::is_move_assignable_v<T> &&
(!std::is_trivially_move_assignable_v<T>);
/**
* @brief Move assigns the value from \p rhs if it has one.
*/
constexpr optional& operator=(optional&&)
requires std::is_move_constructible_v<T> && std::is_move_assignable_v<T> &&
std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>
= default;
/**
* @brief Assigns the contained value from \p u, destroying the old value if there
*
* @tparam U The type of the value to assign.
* @param u The value to assign.
* @return optional&
*/
template <class U = T>
constexpr optional& operator=(U&& u)
requires detail::enable_assign_forward<T, U>;
/**
* @brief Assigns the contained value from \p rhs if it has one, destroying the old value if there
*
*/
template <class U>
constexpr optional& operator=(const optional<U>& rhs)
requires (detail::enable_assign_from_other<T, U, const U&>);
/**
* @brief Assigns the contained value from \p rhs if it has one, destroying the old value if there
*/
template <class U>
constexpr optional& operator=(optional<U>&& rhs)
requires (detail::enable_assign_from_other<T, U, U>);
/**
* @brief Constructs the value in-place, destroying the current one if there
*
* @tparam Args
* @param args The argument list to use in emplacement construction.
* @return T&
*/
template <class... Args>
constexpr T& emplace(Args&&... args);
/**
* @brief Constructs the value in-place using the given arguments, destroying the current one if there
*
* @tparam U
* @tparam Args
* @param il The initializer list to use in emplacement construction.
* @param args The argument list to use in emplacement construction.
* @return T&
*/
template <class U, class... Args>
constexpr T& emplace(std::initializer_list<U> il, Args&&... args);
// \ref{optional.swap}, swap
/**
* @brief Swaps this optional with the other.
*
* @param rhs The optional to swap with.
*/
constexpr void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_swappable<T>::value);
// \ref{optional.iterators}, iterator support
/**
* @brief Returns an iterator to the beginning of the optional.
* @return iterator
*/
constexpr iterator begin() noexcept;
/**
* @brief Returns a const iterator to the beginning of the optional.
* @return const_iterator
*/
constexpr const_iterator begin() const noexcept;
/**
* @brief Returns an iterator to the end of the optional.
* @return iterator
*/
constexpr iterator end() noexcept;
/**
* @brief Returns a const iterator to the end of the optional.
* @return const_iterator
*/
constexpr const_iterator end() const noexcept;
// \ref{optional.observe}, observers
/**
* @brief Returns a pointer to the contained value.
*/
constexpr const T* operator->() const;
/**
* @brief Returns a pointer to the contained value.
*
* @return T*
*/
constexpr T* operator->();
/**
* @brief Returns a reference to the contained value.
*
* @return T&
*/
constexpr T& operator*() &;
/**
* @brief Returns a reference to the contained value.
*
* @return const T&
*/
constexpr const T& operator*() const&;
/**
* @brief Returns a reference to the contained value.
*
* @return T&&
*/
constexpr T&& operator*() &&;
/**
* @brief Converts the optional to a boolean indicating whether it has a value.
*
* @return bool
*/
constexpr explicit operator bool() const noexcept;
/**
* @brief Returns whether or not the optional has a value.
*
* @return bool
*/
constexpr bool has_value() const noexcept;
/**
* @brief Returns a reference to the contained value.
*
* @return T&
*/
constexpr T& value() &;
/**
* @brief Returns a reference to the contained value.
*
* @return const T&
*/
constexpr const T& value() const&;
/**
* @brief Returns a reference to the contained value.
*
* @return T&&
*/
constexpr T&& value() &&;
/**
* @brief Returns the contained value if there is one, otherwise returns `u`.
*
* @tparam U The type of the alternate value
* @param u The value to return in the empty case
* @return T
*/
template <class U = std::remove_cv_t<T>>
constexpr std::remove_cv_t<T> value_or(U&& u) const&;
/**
* @brief Returns the contained value if there is one, otherwise returns `u`.
*
* @tparam U The type of the alternate value
* @param u The value to return in the empty case
* @return T
*/
template <class U = std::remove_cv_t<T>>
constexpr std::remove_cv_t<T> value_or(U&& u) &&;
// \ref{optional.monadic}, monadic operations
/**
* @brief Applies a function to the contained value if there is one.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return auto
*
* @details
* The return type is the same as `std::invoke_result_t<F, T&>`,
* but wrapped in an optional. The function \p f must return an optional type.
*/
template <class F>
constexpr auto and_then(F&& f) &;
/**
* @brief Applies a function to the contained value if there is one.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return auto
*
* @details
* The return type is the same as `std::invoke_result_t<F, T&>`,
* but wrapped in an optional. The function \p f must return an optional type.
*/
template <class F>
constexpr auto and_then(F&& f) &&;
/**
* @brief Applies a function to the contained value if there is one.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return auto
*
* @details
* The return type is the same as `std::invoke_result_t<F, T&>`,
* but wrapped in an optional. The function \p f must return an optional type.
*/
template <class F>
constexpr auto and_then(F&& f) const&;
/**
* @brief Applies a function to the contained value if there is one.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return auto
*
* @details
* The return type is the same as `std::invoke_result_t<F, T&>`,
* but wrapped in an optional. The function \p f must return an optional type.
*/
template <class F>
constexpr auto and_then(F&& f) const&&;
/**
* @brief Returns an optional containing the result of applying \p f to the
* contained value, or an empty optional if there is no contained value.
*
* @tparam F
* @param f An invocable to apply to the contained value.
* @return optional
*/
template <class F>
constexpr auto transform(F&& f) &;
/**
* @brief Returns an optional containing the result of applying \p f to the
* contained value, or an empty optional if there is no contained value.
*
* @tparam F
* @param f An invocable to apply to the contained value.
* @return auto
*/
template <class F>
constexpr auto transform(F&& f) &&;
/**
* @brief Returns an optional containing the result of applying \p f to the
* contained value, or an empty optional if there is no contained value.
*
* @tparam F
* @param f An invocable to apply to the contained value.
* @return auto
*/
template <class F>
constexpr auto transform(F&& f) const&;
/**
* @brief Returns an optional containing the result of applying \p f to the
* contained value, or an empty optional if there is no contained value.
*
* @tparam F
* @param f An invocable to apply to the contained value.
* @return auto
*/
template <class F>
constexpr auto transform(F&& f) const&&;
/**
* @brief Returns an optional containing the contained value if it has one, or the result of applying \p f to the
* optional if it does not.
*
* @tparam F An invocable type returning an optional.
* @param f The invocable to call if the optional is disengaged.
* @return optional
*/
template <class F>
constexpr optional or_else(F&& f) const&
requires (std::invocable<F> && std::copy_constructible<T>);
/**
* @brief Returns an optional containing the contained value if it has one, or
* the result of calling \p f if it does not.
*
* @tparam F An invocable type returning an optional.
* @param f The invocable to call if the optional is disengaged.
* @return auto
*/
template <class F>
constexpr optional or_else(F&& f) &&
requires (std::invocable<F> && std::move_constructible<T>);


[pre-commit] reported by reviewdog 🐶

// \ref{optional.mod}, modifiers
/**
* @brief Resets the optional to an empty state, destroying the contained value if there is one.
*
*/
constexpr void reset() noexcept;
private:
struct empty {};
union {
/**
* @brief The empty state of the optional.
*
*/
empty _{};
/**
* @brief The contained value of the optional.
*
*/
T value_;
};
bool engaged_ = false;
template <class... Args>
constexpr void construct(Args&&... args) {
std::construct_at(std::addressof(value_), std::forward<Args>(args)...);
engaged_ = true;
}


[pre-commit] reported by reviewdog 🐶

constexpr void hard_reset() noexcept {
std::destroy_at(std::addressof(value_));
engaged_ = false;
}


[pre-commit] reported by reviewdog 🐶

template <class U>
friend class optional;


[pre-commit] reported by reviewdog 🐶

template <class F, class Arg>
constexpr optional(detail::from_function_t, F&& f, Arg&& arg)
: value_(std::invoke(std::forward<F>(f), std::forward<Arg>(arg))), engaged_(true) {}


[pre-commit] reported by reviewdog 🐶

public:
/**
* @brief Construct a new bad optional access object
*
*/
bad_optional_access() = default;
/**
* @brief Get the error message for bad optional access
*
* @return const char*
*/
const char* what() const noexcept { return "Optional has no value"; }


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr optional<T>::optional(nullopt_t) noexcept {}


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(const optional& rhs)
requires std::is_copy_constructible_v<T> && (!std::is_trivially_copy_constructible_v<T>)


[pre-commit] reported by reviewdog 🐶

if (rhs.has_value()) {
construct(rhs.value_);
}


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(optional&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
requires std::is_move_constructible_v<T> && (!std::is_trivially_move_constructible_v<T>)


[pre-commit] reported by reviewdog 🐶

if (rhs.has_value()) {
construct(std::move(rhs.value_));
}


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(in_place_t, Args&&... args)
requires std::is_constructible_v<T, Args...>


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(in_place_t, std::initializer_list<U> il, Args&&... args)
requires std::is_constructible_v<T, std::initializer_list<U>&, Args&&...>


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(U&& u)
requires detail::enable_forward_value<T, U>


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(const optional<U>& rhs)
requires (detail::enable_from_other<T, U, const U&>)


[pre-commit] reported by reviewdog 🐶

if (rhs.has_value()) {
construct(*rhs);
}


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::optional(optional<U>&& rhs)
requires (detail::enable_from_other<T, U, U &&>)


[pre-commit] reported by reviewdog 🐶

if (rhs.has_value()) {
construct(*std::move(rhs));
}


[pre-commit] reported by reviewdog 🐶

requires (!std::is_trivially_destructible_v<T>)


[pre-commit] reported by reviewdog 🐶

if (has_value())
std::destroy_at(std::addressof(value_));


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>& optional<T>::operator=(nullopt_t) noexcept {
reset();
return *this;


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>& optional<T>::operator=(const optional<T>& rhs)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
(!std::is_trivially_copy_assignable_v<T>)


[pre-commit] reported by reviewdog 🐶

if (!rhs.has_value())
reset();
else if (has_value())
value_ = rhs.value_;
else
construct(rhs.value_);
return *this;


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>&
optional<T>::operator=(optional<T>&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
requires std::is_move_constructible_v<T> && std::is_move_assignable_v<T> &&
(!std::is_trivially_move_assignable_v<T>)


[pre-commit] reported by reviewdog 🐶

if (!rhs.has_value())
reset();
else if (has_value())
value_ = std::move(rhs.value_);
else
construct(std::move(rhs.value_));
return *this;


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>& optional<T>::operator=(U&& u)
requires detail::enable_assign_forward<T, U>


[pre-commit] reported by reviewdog 🐶

if (has_value()) {
value_ = std::forward<U>(u);
} else {
construct(std::forward<U>(u));
}


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>& optional<T>::operator=(const optional<U>& rhs)
requires (detail::enable_assign_from_other<T, U, const U&>)


[pre-commit] reported by reviewdog 🐶

if (has_value()) {
if (rhs.has_value()) {
value_ = *rhs;
} else {
hard_reset();
}


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

else if (rhs.has_value()) {
construct(*rhs);
}


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>& optional<T>::operator=(optional<U>&& rhs)
requires (detail::enable_assign_from_other<T, U, U>)


[pre-commit] reported by reviewdog 🐶

if (has_value()) {
if (rhs.has_value()) {
value_ = *std::move(rhs);
} else {
hard_reset();
}


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

else if (rhs.has_value()) {
construct(*std::move(rhs));
}


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

constexpr T& optional<T>::emplace(Args&&... args) {
static_assert(std::is_constructible_v<T, Args&&...>);
*this = nullopt;
construct(std::forward<Args>(args)...);
return value();


[pre-commit] reported by reviewdog 🐶

constexpr T& optional<T>::emplace(std::initializer_list<U> il, Args&&... args) {
static_assert(std::is_constructible_v<T, std::initializer_list<U>&, Args&&...>);
*this = nullopt;
construct(il, std::forward<Args>(args)...);
return value();


[pre-commit] reported by reviewdog 🐶

inline constexpr void optional<T>::swap(optional<T>& rhs) noexcept(std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_swappable<T>::value) {
static_assert(std::is_move_constructible_v<T>);
using std::swap;
if (has_value()) {
if (rhs.has_value()) {
swap(value(), *rhs);
} else {
std::construct_at(std::addressof(rhs.value_), std::move(value_));
value_.T::~T();
}
} else if (rhs.has_value()) {
std::construct_at(std::addressof(value_), std::move(rhs.value_));
rhs.value_.T::~T();


[pre-commit] reported by reviewdog 🐶

swap(engaged_, rhs.engaged_);


[pre-commit] reported by reviewdog 🐶

return iterator(has_value() ? std::addressof(value_) : nullptr);


[pre-commit] reported by reviewdog 🐶

inline constexpr optional<T>::const_iterator optional<T>::begin() const noexcept {
return const_iterator(has_value() ? std::addressof(value_) : nullptr);


[pre-commit] reported by reviewdog 🐶

return begin() + has_value();


[pre-commit] reported by reviewdog 🐶

return begin() + has_value();


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr const T* optional<T>::operator->() const {
return std::addressof(value_);


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr T* optional<T>::operator->() {
return std::addressof(value_);


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr T& optional<T>::operator*() & {
return value_;


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr const T& optional<T>::operator*() const& {
return value_;


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr T&& optional<T>::operator*() && {
return std::move(value_);


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr T& optional<T>::value() & {
return has_value() ? value_ : throw bad_optional_access();


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr const T& optional<T>::value() const& {
return has_value() ? value_ : throw bad_optional_access();


[pre-commit] reported by reviewdog 🐶

template <class T>
inline constexpr T&& optional<T>::value() && {


[pre-commit] reported by reviewdog 🐶

if (has_value()) {
return std::move(value_);
}
throw bad_optional_access();


[pre-commit] reported by reviewdog 🐶

return has_value() ? std::move(value_) : throw bad_optional_access();


[pre-commit] reported by reviewdog 🐶

inline constexpr std::remove_cv_t<T> optional<T>::value_or(U&& u) const& {
using X = std::remove_cv_t<T>;
static_assert(std::is_convertible_v<const T&, X>, "Must be able to convert const T& to remove_cv_t<T>");
static_assert(std::is_convertible_v<U, X>, "Must be able to convert u to remove_cv_t<T>");
if (has_value())
return value_;
return std::forward<U>(u);


[pre-commit] reported by reviewdog 🐶

inline constexpr std::remove_cv_t<T> optional<T>::value_or(U&& u) && {
using X = std::remove_cv_t<T>;
static_assert(std::is_convertible_v<T, X>, "Must be able to convert T to remove_cv_t<T>");
static_assert(std::is_convertible_v<U, X>, "Must be able to convert u to remove_cv_t<T>");
if (has_value()) {
return std::move(value_);
}
return std::forward<U>(u);


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::and_then(F&& f) & {
using U = std::invoke_result_t<F, T&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
if (has_value()) {
return std::invoke(std::forward<F>(f), value_);
} else {
return std::remove_cvref_t<U>();
}


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::and_then(F&& f) && {
using U = std::invoke_result_t<F, T&&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
if (has_value()) {
return std::invoke(std::forward<F>(f), std::move(value_));
} else {
return std::remove_cvref_t<U>();
}


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::and_then(F&& f) const& {
using U = std::invoke_result_t<F, const T&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
if (has_value()) {
return std::invoke(std::forward<F>(f), value_);
} else {
return std::remove_cvref_t<U>();
}


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::and_then(F&& f) const&& {
using U = std::invoke_result_t<F, const T&&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
if (has_value()) {
return std::invoke(std::forward<F>(f), std::move(value_));
} else {
return std::remove_cvref_t<U>();
}


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::transform(F&& f) & {
using U = std::invoke_result_t<F, T&>;
static_assert(!std::is_array_v<U>);
static_assert(!std::is_same_v<U, in_place_t>);
static_assert(!std::is_same_v<U, nullopt_t>);
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
return (has_value()) ? optional<U>{detail::from_function, std::forward<F>(f), value_} : optional<U>{};


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::transform(F&& f) && {
using U = std::invoke_result_t<F, T&&>;
static_assert(!std::is_array_v<U>);
static_assert(!std::is_same_v<U, in_place_t>);
static_assert(!std::is_same_v<U, nullopt_t>);
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
return (has_value()) ? optional<U>{detail::from_function, std::forward<F>(f), std::move(value_)} : optional<U>{};


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::transform(F&& f) const& {
using U = std::invoke_result_t<F, const T&>;
static_assert(!std::is_array_v<U>);
static_assert(!std::is_same_v<U, in_place_t>);
static_assert(!std::is_same_v<U, nullopt_t>);
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
return (has_value()) ? optional<U>{detail::from_function, std::forward<F>(f), value_} : optional<U>{};


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T>::transform(F&& f) const&& {
using U = std::invoke_result_t<F, const T&>;
static_assert(!std::is_array_v<U>);
static_assert(!std::is_same_v<U, in_place_t>);
static_assert(!std::is_same_v<U, nullopt_t>);
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
return (has_value()) ? optional<U>{detail::from_function, std::forward<F>(f), std::move(value_)} : optional<U>{};


[pre-commit] reported by reviewdog 🐶

* @brief Returns an optional containing the contained value if it has one, or the result of calling


[pre-commit] reported by reviewdog 🐶

constexpr optional<T> optional<T>::or_else(F&& f) const&
requires (std::invocable<F> && std::copy_constructible<T>)


[pre-commit] reported by reviewdog 🐶

static_assert(std::is_same_v<std::remove_cvref_t<std::invoke_result_t<F>>, optional>);
if (has_value())
return value_;


[pre-commit] reported by reviewdog 🐶

return std::forward<F>(f)();


[pre-commit] reported by reviewdog 🐶

* @brief Returns an optional containing the contained value if it has one, or the result of calling


[pre-commit] reported by reviewdog 🐶

constexpr optional<T> optional<T>::or_else(F&& f) &&
requires (std::invocable<F> && std::move_constructible<T>)


[pre-commit] reported by reviewdog 🐶

static_assert(std::is_same_v<std::remove_cvref_t<std::invoke_result_t<F>>, optional>);
if (has_value())
return std::move(value_);


[pre-commit] reported by reviewdog 🐶

return std::forward<F>(f)();


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr void optional<T>::reset() noexcept {
if constexpr (!std::is_trivially_destructible_v<T>) {
if (has_value())
value_.~T();
}
engaged_ = false;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_eq_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return static_cast<bool>(lhs) == static_cast<bool>(rhs) && (!lhs || *lhs == *rhs);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_ne_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return static_cast<bool>(lhs) != static_cast<bool>(rhs) || (static_cast<bool>(lhs) && *lhs != *rhs);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_lt_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return static_cast<bool>(rhs) && (!lhs || *lhs < *rhs);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_gt_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return static_cast<bool>(lhs) && (!rhs || *lhs > *rhs);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_le_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !lhs || (static_cast<bool>(rhs) && *lhs <= *rhs);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs)
requires detail::optional_ge_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !rhs || (static_cast<bool>(lhs) && *lhs >= *rhs);


[pre-commit] reported by reviewdog 🐶

constexpr std::compare_three_way_result_t<T, U> operator<=>(const optional<T>& x, const optional<U>& y) {
return x && y ? *x <=> *y : bool(x) <=> bool(y);


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept {
return !lhs;


[pre-commit] reported by reviewdog 🐶

constexpr std::strong_ordering operator<=>(const optional<T>& x, nullopt_t) noexcept {
return bool(x) <=> false;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_eq_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return lhs && *lhs == rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator==(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_eq_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return rhs && lhs == *rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator!=(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_ne_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !lhs || *lhs != rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator!=(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_ne_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !rhs || lhs != *rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_lt_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !lhs || *lhs < rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_lt_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return rhs && lhs < *rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_gt_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return lhs && *lhs > rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_gt_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !rhs || lhs > *rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<=(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_le_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !lhs || *lhs <= rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator<=(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_le_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return rhs && lhs <= *rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>=(const optional<T>& lhs, const U& rhs)
requires (!detail::is_optional<U>) && detail::optional_ge_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return lhs && *lhs >= rhs;


[pre-commit] reported by reviewdog 🐶

constexpr bool operator>=(const T& lhs, const optional<U>& rhs)
requires (!detail::is_optional<T>) && detail::optional_ge_rel<T, U>


[pre-commit] reported by reviewdog 🐶

return !rhs || lhs >= *rhs;


[pre-commit] reported by reviewdog 🐶

requires (!is_derived_from_optional<U>) && std::three_way_comparable_with<T, U>
constexpr std::compare_three_way_result_t<T, U> operator<=>(const optional<T>& x, const U& v) {
return bool(x) ? *x <=> v : std::strong_ordering::less;


[pre-commit] reported by reviewdog 🐶

constexpr void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
requires std::is_move_constructible_v<T> && std::is_swappable_v<T>


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

constexpr optional<std::decay_t<T>>
make_optional(T&& t) noexcept(std::is_nothrow_constructible_v<optional<std::decay_t<T>>, T>)
requires std::is_constructible_v<std::decay_t<T>, T>


[pre-commit] reported by reviewdog 🐶

return optional<std::decay_t<T>>{std::forward<T>(t)};


[pre-commit] reported by reviewdog 🐶

constexpr optional<T> make_optional(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
requires std::is_constructible_v<T, Args...>


[pre-commit] reported by reviewdog 🐶

static_assert(!std::is_reference_v<T>, "May not make an optional containing a reference");
return optional<T>{in_place, std::forward<Args>(args)...};


[pre-commit] reported by reviewdog 🐶

make_optional(std::initializer_list<U> init_list,
Args&&... args) noexcept(std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
requires std::is_constructible_v<T, std::initializer_list<U>&, Args...>


[pre-commit] reported by reviewdog 🐶

static_assert(!std::is_reference_v<U>, "Can not make optional from initializer_list of references.");
return optional<T>{in_place, init_list, std::forward<Args>(args)...};


[pre-commit] reported by reviewdog 🐶

(!std::is_reference_v<From> && std::is_convertible_v<std::remove_cvref_t<From>*, std::remove_cvref_t<To>*>) ||


[pre-commit] reported by reviewdog 🐶

(std::is_lvalue_reference_v<To> && std::is_const_v<std::remove_reference_t<To>> &&
std::is_convertible_v<From, const std::remove_cvref_t<To>&&> &&
!std::is_convertible_v<From, std::remove_cvref_t<To>&>));


[pre-commit] reported by reviewdog 🐶

template <class T>
class optional<T&> {
public:
/**
* @brief The type of the value contained in the optional.
*
*/
using value_type = T;
/**
* @brief The type of the iterator for the optional.
*
*/
using iterator = detail::contiguous_iterator<T,
optional>; // see [optionalref.iterators]
public:
// \ref{optionalref.ctor}, constructors
/**
* @brief Default constructor.
*/
constexpr optional() noexcept = default;
/**
* @brief Constructs an empty optional.
*/
constexpr optional(nullopt_t) noexcept : optional() {}
/**
* @brief Copy constructor.
*
* Constructs an empty optional if the rhs is empty, otherwise constructs
* the contained value from the rhs.
*/
constexpr optional(const optional& rhs) noexcept = default;
/**
* @brief In-place constructor.
*
* @tparam Arg
* @param arg The value to construct in-place from.
*/
template <class Arg>
requires (std::is_constructible_v<T&, Arg> && !detail::reference_constructs_from_temporary_v<T&, Arg>)
constexpr explicit optional(in_place_t, Arg&& arg);
/**
* @brief Construct from a U
* @tparam U
* @param u The value to construct from.
* @details
* Constructs the contained value from `u` if it is convertible to `T&`.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, U> && !(std::is_same_v<std::remove_cvref_t<U>, in_place_t>) &&
!(std::is_same_v<std::remove_cvref_t<U>, optional>) &&
!detail::reference_constructs_from_temporary_v<T&, U>)
constexpr explicit(!std::is_convertible_v<U, T&>)
optional(U&& u) noexcept(std::is_nothrow_constructible_v<T&, U>) {
convert_ref_init_val(u);
}
/**
* @brief Constructs an optional from a U, but deletes the constructor if
*
* @tparam U
*/
template <class U>
requires (std::is_constructible_v<T&, U> && !(std::is_same_v<std::remove_cvref_t<U>, in_place_t>) &&
!(std::is_same_v<std::remove_cvref_t<U>, optional>) &&
detail::reference_constructs_from_temporary_v<T&, U>)
constexpr optional(U&& u) = delete;
// The full set of 4 overloads on optional<U> by value category, doubled to
// 8 by deleting if reference_constructs_from_temporary_v is true. This
// allows correct constraints by propagating the value category from the
// optional to the value within the rhs.
/**
* @brief Constructs an optional from another optional of type U.
*
* @tparam U
* @param rhs The optional to construct from.
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, U&> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U&>)
constexpr explicit(!std::is_convertible_v<U&, T&>)
optional(optional<U>& rhs) noexcept(std::is_nothrow_constructible_v<T&, U&>);
/**
* @brief Constructs an optional from another optional of type U.
* @param rhs The optional to construct from.
* @tparam U
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, const U&> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, const U&>)
constexpr explicit(!std::is_convertible_v<const U&, T&>)
optional(const optional<U>& rhs) noexcept(std::is_nothrow_constructible_v<T&, const U&>);
/**
* @brief Constructs an optional from another optional of type U.
* @param rhs The optional to construct from.
* @tparam U
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, U> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U>)
constexpr explicit(!std::is_convertible_v<U, T&>)
optional(optional<U>&& rhs) noexcept(noexcept(std::is_nothrow_constructible_v<T&, U>));
/**
* @brief Constructs an optional from another optional of type U.
*
* @tparam U The type contained the right hand side optional.
* @param rhs The optional to construct from.
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, const U> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, const U>)
constexpr explicit(!std::is_convertible_v<const U, T&>)
optional(const optional<U>&& rhs) noexcept(noexcept(std::is_nothrow_constructible_v<T&, const U>));
/**
* @brief Constructs an optional from another optional of type U
*
* @tparam U
* @param rhs
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, U&> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && detail::reference_constructs_from_temporary_v<T&, U&>)
constexpr optional(optional<U>& rhs) = delete;
/**
* @brief Constructs an optional from another optional of type U
*
* @tparam U
* @param rhs
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, const U&> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && detail::reference_constructs_from_temporary_v<T&, const U&>)
constexpr optional(const optional<U>& rhs) = delete;
/**
* @brief Constructs an optional from another optional of type U
*
* @tparam U
* @param rhs
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, U> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && detail::reference_constructs_from_temporary_v<T&, U>)
constexpr optional(optional<U>&& rhs) = delete;
/**
* @brief Constructs an optional from another optional of type U
*
* @tparam U
* @param rhs
* @details
* Constructs the contained value from the rhs if it has a value, otherwise
* constructs an empty optional.
* If `T&` can be constructed from a temporary, this constructor is
* deleted to prevent binding a temporary to a reference.
*/
template <class U>
requires (std::is_constructible_v<T&, const U> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && detail::reference_constructs_from_temporary_v<T&, const U>)
constexpr optional(const optional<U>&& rhs) = delete;
// \ref{optionalref.dtor}, destructor
/**
* @brief Destructor.
*
* @details
* Does not destroy the contained value, as it is a reference.
*/
constexpr ~optional() = default;
// \ref{optionalref.assign}, assignment
/**
* @brief Nullopt assignment operator.
*
* @return optional&
*
* @details
* Destroys the current value if there is one, and leaves the optional
* in an empty state.
*/
constexpr optional& operator=(nullopt_t) noexcept;
/**
* @brief Assignment operator.
*
* @param rhs The value to assign.
* @return optional&
* @details
* If `rhs` has a value, assigns it to the contained value. Otherwise resets
* the contained value in `*this`.
*/
constexpr optional& operator=(const optional& rhs) noexcept = default;
/**
* @brief Emplaces a new value in the optional, destroying the current one
* if the optional is engaged.
*
* @tparam U The type of the value to emplace.
* @param u The value to emplace.
* @return T&
* @details
* Constructs the contained value from `u` if it is convertible to `T&`.
*/
template <class U>
requires (std::is_constructible_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U>)
constexpr T& emplace(U&& u) noexcept(std::is_nothrow_constructible_v<T&, U>);
// \ref{optionalref.swap}, swap
/**
* @brief Swaps the contents of this optional with another.
*
* @param rhs The value to swap with.
*/
constexpr void swap(optional& rhs) noexcept;
// \ref{optional.iterators}, iterator support
/**
* @brief Returns an iterator to the beginning of the optional.
*
* @return iterator
*/
constexpr iterator begin() const noexcept;
/**
* @brief Returns an iterator to the end of the optional.
*
* @return iterator
*/
constexpr iterator end() const noexcept;
// \ref{optionalref.observe}, observers
/**
* @brief Returns a pointer to the contained value.
*
* @return T*
*/
constexpr T* operator->() const noexcept;
/**
* @brief Returns a reference to the contained value.
*
* @return T&
*/
constexpr T& operator*() const noexcept;
/**
* @brief Converts the optional to a boolean value.
*
* @return bool
*/
constexpr explicit operator bool() const noexcept;
/**
* @brief Checks if the optional has a value.
*
* @return bool
*/
constexpr bool has_value() const noexcept;
/**
* @brief Returns the contained value if there is one, otherwise throws
*
* @return T&
*/
constexpr T& value() const;
// LWG4304. std::optional<NonReturnable&> is ill-formed due to value_o
// Resolution:
// -?- Constraints: T is a non-array object type.
// -?- Remarks: The return type is unspecified if T is an array type or a
// non-object type. [Note ?: This is to avoid the declaration being
// ill-formed. — end note]
//
// Implementer Note: Using decay_t as a detail as it is remove_cv_t for
// non-array objects, and produces a valid type for arrays and functions,
// which are otherwise `required` out.
/**
* @brief Returns the contained value if there is one, otherwise returns `u`.
*
* @tparam U The type of the alternate value
* @param u The value to return in the empty case
* @return std::remove_cv_t<T>
*/
template <class U = std::remove_cv_t<T>>
requires (std::is_object_v<T> && !std::is_array_v<T>)
constexpr std::decay_t<T> value_or(U&& u) const;
// \ref{optionalref.monadic}, monadic operations
/**
* @brief Applies a function to the contained value if there is one.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return auto
*
* @details
* The return type is the same as `std::invoke_result_t<F, T&>`,
* but wrapped in an optional. The function \p f must return an optional type.
*/
template <class F>
constexpr auto and_then(F&& f) const;
/**
* @brief Applies a function to the contained value if there is one.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return optional<std::invoke_result_t<F, T&>>
*
* @details
* The return type is the same as `std::invoke_result_t<F, T&>`,
* but wrapped in an optional.
*/
template <class F>
constexpr optional<std::invoke_result_t<F, T&>> transform(F&& f) const;
/**
* @brief Calls a function if the optional is empty.
*
* @tparam F The type of the invocable
* @param f The invocable to apply to the contained value
* @return optional
* @details
* The return type is the same as the return type of \p f, which must
* return an optional type.
*/
template <class F>
constexpr optional or_else(F&& f) const
requires (std::invocable<F>);
// \ref{optional.mod}, modifiers
/**
* @brief Resets the optional to an empty state.
*
*/
constexpr void reset() noexcept;
private:
T* value_ = nullptr; // exposition only
// \ref{optionalref.expos}, exposition only helper functions
template <class U>
constexpr void convert_ref_init_val(U&& u) {
// Creates a variable, \tcode{r},
// as if by \tcode{T\& r(std::forward<U>(u));}
// and then initializes \exposid{val} with \tcode{addressof(r)}
T& r(std::forward<U>(u));
value_ = std::addressof(r);
}
template <class U>
friend class optional;
template <class F, class Arg>
constexpr optional(detail::from_function_t, F&& f, Arg&& arg) {
convert_ref_init_val(std::invoke(std::forward<F>(f), std::forward<Arg>(arg)));
}


[pre-commit] reported by reviewdog 🐶

requires (std::is_constructible_v<T&, Arg> && !detail::reference_constructs_from_temporary_v<T&, Arg>)
constexpr optional<T&>::optional(in_place_t, Arg&& arg) {
convert_ref_init_val(std::forward<Arg>(arg));


[pre-commit] reported by reviewdog 🐶

// requires(std::is_constructible_v<T&, U> && !(is_same_v<remove_cvref_t<U>, in_place_t>) &&
// !(is_same_v<remove_cvref_t<U>, optional<T&>>) && !detail::reference_constructs_from_temporary_v<T&, U>)
// constexpr optional<T&>::optional(U&& u) noexcept(is_nothrow_constructible_v<T&, U>)


[pre-commit] reported by reviewdog 🐶

requires (std::is_constructible_v<T&, U&> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U&>)
constexpr optional<T&>::optional(optional<U>& rhs) noexcept(std::is_nothrow_constructible_v<T&, U&>) {
if (rhs.has_value()) {
convert_ref_init_val(*rhs);
}


[pre-commit] reported by reviewdog 🐶

requires (std::is_constructible_v<T&, const U&> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, const U&>)
constexpr optional<T&>::optional(const optional<U>& rhs) noexcept(std::is_nothrow_constructible_v<T&, const U&>) {
if (rhs.has_value()) {
convert_ref_init_val(*rhs);
}


[pre-commit] reported by reviewdog 🐶

requires (std::is_constructible_v<T&, U> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U>)
constexpr optional<T&>::optional(optional<U>&& rhs) noexcept(noexcept(std::is_nothrow_constructible_v<T&, U>)) {
if (rhs.has_value()) {
convert_ref_init_val(*std::move(rhs));
}


[pre-commit] reported by reviewdog 🐶

requires (std::is_constructible_v<T&, const U> && !std::is_same_v<std::remove_cv_t<T>, optional<U>> &&
!std::is_same_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, const U>)
constexpr optional<T&>::optional(const optional<U>&& rhs) noexcept(
noexcept(std::is_nothrow_constructible_v<T&, const U>)) {
if (rhs.has_value()) {
convert_ref_init_val(*std::move(rhs));
}


[pre-commit] reported by reviewdog 🐶

constexpr optional<T&>& optional<T&>::operator=(nullopt_t) noexcept {
value_ = nullptr;
return *this;


[pre-commit] reported by reviewdog 🐶

requires (std::is_constructible_v<T&, U> && !detail::reference_constructs_from_temporary_v<T&, U>)
constexpr T& optional<T&>::emplace(U&& u) noexcept(std::is_nothrow_constructible_v<T&, U>) {
convert_ref_init_val(std::forward<U>(u));
return *value_;


[pre-commit] reported by reviewdog 🐶

constexpr void optional<T&>::swap(optional<T&>& rhs) noexcept {
std::swap(value_, rhs.value_);


[pre-commit] reported by reviewdog 🐶

constexpr optional<T&>::iterator optional<T&>::begin() const noexcept {
return iterator(has_value() ? value_ : nullptr);


[pre-commit] reported by reviewdog 🐶

constexpr optional<T&>::iterator optional<T&>::end() const noexcept {
return begin() + has_value();


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr T* optional<T&>::operator->() const noexcept {
return value_;


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr T& optional<T&>::operator*() const noexcept {
return *value_;


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr optional<T&>::operator bool() const noexcept {
return value_ != nullptr;


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr bool optional<T&>::has_value() const noexcept {
return value_ != nullptr;


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr T& optional<T&>::value() const {
if (has_value()) {
return *value_;
}
throw bad_optional_access();


[pre-commit] reported by reviewdog 🐶

requires (std::is_object_v<T> && !std::is_array_v<T>)
constexpr std::decay_t<T> optional<T&>::value_or(U&& u) const {
using X = std::remove_cv_t<T>;
static_assert(std::is_convertible_v<T&, X>, "remove_cv_t<T> must be constructible from a T&");
static_assert(std::is_convertible_v<U, X>, "Must be able to convert u to remove_cv_t<T>");
if (has_value()) {
return *value_;
}
return std::forward<U>(u);


[pre-commit] reported by reviewdog 🐶

constexpr auto optional<T&>::and_then(F&& f) const {
using U = std::invoke_result_t<F, T&>;
static_assert(detail::is_optional<U>, "F must return an optional");
if (has_value()) {
return std::invoke(std::forward<F>(f), *value_);
} else {
return std::remove_cvref_t<U>();
}


[pre-commit] reported by reviewdog 🐶

constexpr optional<std::invoke_result_t<F, T&>> optional<T&>::transform(F&& f) const {
using U = std::invoke_result_t<F, T&>;
static_assert(!std::is_same_v<std::remove_cvref_t<U>, in_place_t>, "Result must not be in_place_t");
static_assert(!std::is_same_v<std::remove_cvref_t<U>, nullopt_t>, "Result must not be nullopt_t");
static_assert((std::is_object_v<U> && !std::is_array_v<U>) || std::is_lvalue_reference_v<U>,
"Result must be an non-array object or an lvalue reference");
if (has_value()) {
return optional<U>{detail::from_function, std::forward<F>(f), *value_};
} else {
return optional<U>{};
}


[pre-commit] reported by reviewdog 🐶

* @brief Returns an optional containing the contained value if it has one, or the result of calling


[pre-commit] reported by reviewdog 🐶

constexpr optional<T&> optional<T&>::or_else(F&& f) const


[pre-commit] reported by reviewdog 🐶

requires (std::invocable<F>)


[pre-commit] reported by reviewdog 🐶

using U = std::invoke_result_t<F>;
static_assert(std::is_same_v<std::remove_cvref_t<U>, optional>, "Result must be an optional");
if (has_value()) {
return *this;
} else {
return std::forward<F>(f)();
}


[pre-commit] reported by reviewdog 🐶

template <class T>
constexpr void optional<T&>::reset() noexcept {
value_ = nullptr;


[pre-commit] reported by reviewdog 🐶

requires requires(T a) {
{ std::hash<remove_const_t<T>>{}(a) } -> std::convertible_to<std::size_t>;
}


[pre-commit] reported by reviewdog 🐶

static_assert(!is_reference_v<T>, "hash is not enabled for reference types");
/**
* @brief Hashes the optional value.
*
* @param o
* @return size_t
*/
size_t operator()(const beman::optional::optional<T>& o) const noexcept(noexcept(hash<remove_const_t<T>>{}(*o))) {
if (o) {
return std::hash<std::remove_const_t<T>>{}(*o);
} else {
return 0;
}


[pre-commit] reported by reviewdog 🐶


[pre-commit] reported by reviewdog 🐶

CHECK((uintptr_t)c.begin() == (uintptr_t)std::addressof(*c.try_emplace_back(2, 3.5)));


[pre-commit] reported by reviewdog 🐶

CHECK((uintptr_t)(c.begin() + 1) == (uintptr_t)std::addressof(*c.try_emplace_back(3, 4.5)));

Comment thread include/beman/inplace_vector/inplace_vector.hpp Outdated
Comment thread include/beman/inplace_vector/inplace_vector.hpp Outdated
Comment thread include/beman/inplace_vector/inplace_vector.hpp Outdated
Comment thread include/beman/inplace_vector/inplace_vector.hpp Outdated
Comment thread include/beman/optional/detail/iterator.hpp Outdated
Comment thread include/beman/optional/detail/stl_interfaces/iterator_interface.hpp Outdated
Comment thread include/beman/optional/detail/stl_interfaces/iterator_interface.hpp Outdated
Comment thread include/beman/optional/detail/stl_interfaces/iterator_interface.hpp Outdated
Comment thread include/beman/optional/detail/stl_interfaces/iterator_interface.hpp Outdated
Comment thread include/beman/optional/detail/stl_interfaces/iterator_interface.hpp Outdated
#ifndef BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_FWD_HPP
#define BEMAN_OPTIONAL_DETAIL_STL_INTERFACES_FWD_HPP

#include <beman/optional/detail/stl_interfaces/config.hpp>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's weird that there's a detail include from optional here....

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I think the issue here is we're introducing a dependence on beman optional -- is that right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the original issue suggested using beman optional so i decided to go along with that
there's every chance i've mishandled bringing int the dependency

@@ -0,0 +1,85 @@
// include/beman/optional/detail/stl_interfaces/fwd.hpp -*-C++-*-

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy pasta?

@wusatosi

Copy link
Copy Markdown
Member

Thank you for your contribution, please allow some time to review.

@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 98.726% (+0.08%) from 98.649% — redraincatching:return-types into bemanproject:main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P3981 Better return types in std::inplace_vector and std::exception_ptr_cast

4 participants