Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 29 additions & 24 deletions include/beman/optional26/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ concept enable_assign_from_other =
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>));
(!std::is_same_v<std::remove_cv_t<T>, nullopt_t>),
"T must not be in_place_t or nullopt_t");

struct empty {};
union {
Expand Down Expand Up @@ -487,7 +488,7 @@ class optional {
template <class F>
constexpr auto and_then(F&& f) & {
using U = std::invoke_result_t<F, T&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
if (has_value()) {
return std::invoke(std::forward<F>(f), value_);
} else {
Expand All @@ -498,7 +499,7 @@ class optional {
template <class F>
constexpr auto and_then(F&& f) && {
using U = std::invoke_result_t<F, T&&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
if (has_value()) {
return std::invoke(std::forward<F>(f), std::move(value_));
} else {
Expand All @@ -509,7 +510,7 @@ class optional {
template <class F>
constexpr auto and_then(F&& f) const& {
using U = std::invoke_result_t<F, const T&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
if (has_value()) {
return std::invoke(std::forward<F>(f), value_);
} else {
Expand All @@ -520,7 +521,7 @@ class optional {
template <class F>
constexpr auto and_then(F&& f) const&& {
using U = std::invoke_result_t<F, const T&&>;
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
if (has_value()) {
return std::invoke(std::forward<F>(f), std::move(value_));
} else {
Expand All @@ -532,40 +533,44 @@ class optional {
template <class F>
constexpr auto 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
static_assert(!std::is_array_v<U>, "U must not be an array");
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t");
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
"U must be either an object or a reference"); /// References now allowed
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), value_)} : optional<U>{};
}

template <class F>
constexpr auto 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
static_assert(!std::is_array_v<U>, "U must not be an array");
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t type");
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
"U must be either an objecy or a reference"); /// References now allowed
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), std::move(value_))} : optional<U>{};
}

template <class F>
constexpr auto 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
static_assert(!std::is_array_v<U>, "U must not be an array");
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t type");
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
"U must be either an objecy or a reference"); /// References now allowed
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), value_)} : optional<U>{};
}

template <class F>
constexpr auto 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
static_assert(!std::is_array_v<U>, "U must not be an array");
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t type");
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
"U must be either an objecy or a reference"); /// References now allowed
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), value_)} : optional<U>{};
}

Expand Down Expand Up @@ -653,7 +658,7 @@ class optional {
/// one.
template <class... Args>
constexpr T& emplace(Args&&... args) {
static_assert(std::is_constructible_v<T, Args&&...>);
static_assert(std::is_constructible_v<T, Args&&...>, "each parameter pack must be constructible to T");
*this = nullopt;
construct(std::forward<Args>(args)...);
return value();
Expand All @@ -675,7 +680,7 @@ class optional {
/// valueless.
constexpr void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_swappable<T>::value) {
static_assert(std::is_move_constructible_v<T>);
static_assert(std::is_move_constructible_v<T>, "T must be move-constructible");
using std::swap;
if (has_value()) {
if (rhs.has_value()) {
Expand Down Expand Up @@ -1138,7 +1143,7 @@ class optional<T&> {
template <class F>
constexpr optional or_else(F&& f) const {
using U = std::invoke_result_t<F>;
static_assert(std::is_same_v<std::remove_cvref_t<U>, optional>);
static_assert(std::is_same_v<std::remove_cvref_t<U>, optional>, "F must return an optional");
return has_value() ? *value_ : std::forward<F>(f)();
}

Expand Down
2 changes: 1 addition & 1 deletion src/beman/optional26/tests/optional.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ TEST(OptionalTest, HashTest) {
EXPECT_EQ(h3, h4);
EXPECT_NE(h1, h3);

for(int i : std::views::iota(0, 1000)) {
for (int i : std::views::iota(0, 1000)) {
auto h1 = std::hash<beman::optional26::optional<int>>{}(i);
auto h2 = std::hash<int>{}(i);
EXPECT_EQ(h1, h2);
Expand Down