Skip to content

Commit

Permalink
Merge pull request bemanproject#68 from changkhothuychung/static-msg
Browse files Browse the repository at this point in the history
add error messages to static_assert
  • Loading branch information
neatudarius authored Oct 17, 2024
2 parents 863a89c + 25cab9a commit a271c96
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
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

0 comments on commit a271c96

Please sign in to comment.