Skip to content

Commit a271c96

Browse files
authored
Merge pull request bemanproject#68 from changkhothuychung/static-msg
add error messages to static_assert
2 parents 863a89c + 25cab9a commit a271c96

File tree

2 files changed

+30
-25
lines changed

2 files changed

+30
-25
lines changed

include/beman/optional26/optional.hpp

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@ concept enable_assign_from_other =
288288
template <class T>
289289
class optional {
290290
static_assert((!std::is_same_v<T, std::remove_cv_t<in_place_t>>) &&
291-
(!std::is_same_v<std::remove_cv_t<T>, nullopt_t>));
291+
(!std::is_same_v<std::remove_cv_t<T>, nullopt_t>),
292+
"T must not be in_place_t or nullopt_t");
292293

293294
struct empty {};
294295
union {
@@ -487,7 +488,7 @@ class optional {
487488
template <class F>
488489
constexpr auto and_then(F&& f) & {
489490
using U = std::invoke_result_t<F, T&>;
490-
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
491+
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
491492
if (has_value()) {
492493
return std::invoke(std::forward<F>(f), value_);
493494
} else {
@@ -498,7 +499,7 @@ class optional {
498499
template <class F>
499500
constexpr auto and_then(F&& f) && {
500501
using U = std::invoke_result_t<F, T&&>;
501-
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
502+
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
502503
if (has_value()) {
503504
return std::invoke(std::forward<F>(f), std::move(value_));
504505
} else {
@@ -509,7 +510,7 @@ class optional {
509510
template <class F>
510511
constexpr auto and_then(F&& f) const& {
511512
using U = std::invoke_result_t<F, const T&>;
512-
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
513+
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
513514
if (has_value()) {
514515
return std::invoke(std::forward<F>(f), value_);
515516
} else {
@@ -520,7 +521,7 @@ class optional {
520521
template <class F>
521522
constexpr auto and_then(F&& f) const&& {
522523
using U = std::invoke_result_t<F, const T&&>;
523-
static_assert(detail::is_optional<std::remove_cvref_t<U>>);
524+
static_assert(detail::is_optional<std::remove_cvref_t<U>>, "F must return an optional");
524525
if (has_value()) {
525526
return std::invoke(std::forward<F>(f), std::move(value_));
526527
} else {
@@ -532,40 +533,44 @@ class optional {
532533
template <class F>
533534
constexpr auto transform(F&& f) & {
534535
using U = std::invoke_result_t<F, T&>;
535-
static_assert(!std::is_array_v<U>);
536-
static_assert(!std::is_same_v<U, in_place_t>);
537-
static_assert(!std::is_same_v<U, nullopt_t>);
538-
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
536+
static_assert(!std::is_array_v<U>, "U must not be an array");
537+
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
538+
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t");
539+
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
540+
"U must be either an object or a reference"); /// References now allowed
539541
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), value_)} : optional<U>{};
540542
}
541543

542544
template <class F>
543545
constexpr auto transform(F&& f) && {
544546
using U = std::invoke_result_t<F, T&&>;
545-
static_assert(!std::is_array_v<U>);
546-
static_assert(!std::is_same_v<U, in_place_t>);
547-
static_assert(!std::is_same_v<U, nullopt_t>);
548-
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
547+
static_assert(!std::is_array_v<U>, "U must not be an array");
548+
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
549+
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t type");
550+
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
551+
"U must be either an objecy or a reference"); /// References now allowed
549552
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), std::move(value_))} : optional<U>{};
550553
}
551554

552555
template <class F>
553556
constexpr auto transform(F&& f) const& {
554557
using U = std::invoke_result_t<F, const T&>;
555-
static_assert(!std::is_array_v<U>);
556-
static_assert(!std::is_same_v<U, in_place_t>);
557-
static_assert(!std::is_same_v<U, nullopt_t>);
558-
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
558+
static_assert(!std::is_array_v<U>, "U must not be an array");
559+
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
560+
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t type");
561+
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
562+
"U must be either an objecy or a reference"); /// References now allowed
559563
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), value_)} : optional<U>{};
560564
}
561565

562566
template <class F>
563567
constexpr auto transform(F&& f) const&& {
564568
using U = std::invoke_result_t<F, const T&>;
565-
static_assert(!std::is_array_v<U>);
566-
static_assert(!std::is_same_v<U, in_place_t>);
567-
static_assert(!std::is_same_v<U, nullopt_t>);
568-
static_assert(std::is_object_v<U> || std::is_reference_v<U>); /// References now allowed
569+
static_assert(!std::is_array_v<U>, "U must not be an array");
570+
static_assert(!std::is_same_v<U, in_place_t>, "U must not be an inplace type");
571+
static_assert(!std::is_same_v<U, nullopt_t>, "U must not be nullopt_t type");
572+
static_assert(std::is_object_v<U> || std::is_reference_v<U>,
573+
"U must be either an objecy or a reference"); /// References now allowed
569574
return (has_value()) ? optional<U>{std::invoke(std::forward<F>(f), value_)} : optional<U>{};
570575
}
571576

@@ -653,7 +658,7 @@ class optional {
653658
/// one.
654659
template <class... Args>
655660
constexpr T& emplace(Args&&... args) {
656-
static_assert(std::is_constructible_v<T, Args&&...>);
661+
static_assert(std::is_constructible_v<T, Args&&...>, "each parameter pack must be constructible to T");
657662
*this = nullopt;
658663
construct(std::forward<Args>(args)...);
659664
return value();
@@ -675,7 +680,7 @@ class optional {
675680
/// valueless.
676681
constexpr void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value &&
677682
std::is_nothrow_swappable<T>::value) {
678-
static_assert(std::is_move_constructible_v<T>);
683+
static_assert(std::is_move_constructible_v<T>, "T must be move-constructible");
679684
using std::swap;
680685
if (has_value()) {
681686
if (rhs.has_value()) {
@@ -1138,7 +1143,7 @@ class optional<T&> {
11381143
template <class F>
11391144
constexpr optional or_else(F&& f) const {
11401145
using U = std::invoke_result_t<F>;
1141-
static_assert(std::is_same_v<std::remove_cvref_t<U>, optional>);
1146+
static_assert(std::is_same_v<std::remove_cvref_t<U>, optional>, "F must return an optional");
11421147
return has_value() ? *value_ : std::forward<F>(f)();
11431148
}
11441149

src/beman/optional26/tests/optional.t.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ TEST(OptionalTest, HashTest) {
837837
EXPECT_EQ(h3, h4);
838838
EXPECT_NE(h1, h3);
839839

840-
for(int i : std::views::iota(0, 1000)) {
840+
for (int i : std::views::iota(0, 1000)) {
841841
auto h1 = std::hash<beman::optional26::optional<int>>{}(i);
842842
auto h2 = std::hash<int>{}(i);
843843
EXPECT_EQ(h1, h2);

0 commit comments

Comments
 (0)