Skip to content

Commit edde723

Browse files
authored
Implement LWG-3843 and LWG-3940 (#1621)
* Implement LWG-3843 and LWG-3940 This only changes aspects of expected that are related to exceptions, so we do not really care about them too much * Fix error message
1 parent dd6f124 commit edde723

File tree

3 files changed

+118
-39
lines changed

3 files changed

+118
-39
lines changed

libcudacxx/include/cuda/std/__expected/expected.h

+20-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include <cuda/std/__type_traits/negation.h>
5555
#include <cuda/std/__type_traits/remove_cv.h>
5656
#include <cuda/std/__type_traits/remove_cvref.h>
57+
#include <cuda/std/__utility/as_const.h>
5758
#include <cuda/std/__utility/exception_guard.h>
5859
#include <cuda/std/__utility/forward.h>
5960
#include <cuda/std/__utility/in_place.h>
@@ -551,6 +552,8 @@ class expected
551552

552553
_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY constexpr const _Tp& value() const&
553554
{
555+
static_assert(_LIBCUDACXX_TRAIT(is_copy_constructible, _Err),
556+
"expected::value() const& requires is_copy_constructible_v<E>");
554557
if (!this->__has_val_)
555558
{
556559
__throw_bad_expected_access<_Err>(this->__union_.__unex_);
@@ -560,15 +563,21 @@ class expected
560563

561564
_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY constexpr _Tp& value() &
562565
{
566+
static_assert(_LIBCUDACXX_TRAIT(is_copy_constructible, _Err),
567+
"expected::value() & requires is_copy_constructible_v<E>");
563568
if (!this->__has_val_)
564569
{
565-
__throw_bad_expected_access<_Err>(this->__union_.__unex_);
570+
__throw_bad_expected_access<_Err>(_CUDA_VSTD::as_const(this->__union_.__unex_));
566571
}
567572
return this->__union_.__val_;
568573
}
569574

570575
_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY constexpr const _Tp&& value() const&&
571576
{
577+
static_assert(_LIBCUDACXX_TRAIT(is_copy_constructible, _Err),
578+
"expected::value() const&& requires is_copy_constructible_v<E>");
579+
static_assert(_LIBCUDACXX_TRAIT(is_constructible, _Err, decltype(_CUDA_VSTD::move(error()))),
580+
"expected::value() const&& requires is_constructible_v<E, decltype(_CUDA_VSTD::move(error()))>");
572581
if (!this->__has_val_)
573582
{
574583
__throw_bad_expected_access<_Err>(_CUDA_VSTD::move(this->__union_.__unex_));
@@ -578,6 +587,10 @@ class expected
578587

579588
_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY constexpr _Tp&& value() &&
580589
{
590+
static_assert(_LIBCUDACXX_TRAIT(is_copy_constructible, _Err),
591+
"expected::value() && requires is_copy_constructible_v<E>");
592+
static_assert(_LIBCUDACXX_TRAIT(is_constructible, _Err, decltype(_CUDA_VSTD::move(error()))),
593+
"expected::value() && requires is_constructible_v<E, decltype(_CUDA_VSTD::move(error()))>");
581594
if (!this->__has_val_)
582595
{
583596
__throw_bad_expected_access<_Err>(_CUDA_VSTD::move(this->__union_.__unex_));
@@ -1473,6 +1486,8 @@ class expected<void, _Err>
14731486

14741487
_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY constexpr void value() const&
14751488
{
1489+
static_assert(_LIBCUDACXX_TRAIT(is_copy_constructible, _Err),
1490+
"expected::value() const& requires is_copy_constructible_v<E>");
14761491
if (!this->__has_val_)
14771492
{
14781493
__throw_bad_expected_access<_Err>(this->__union_.__unex_);
@@ -1481,6 +1496,10 @@ class expected<void, _Err>
14811496

14821497
_LIBCUDACXX_HIDE_FROM_ABI _LIBCUDACXX_INLINE_VISIBILITY constexpr void value() &&
14831498
{
1499+
static_assert(_LIBCUDACXX_TRAIT(is_copy_constructible, _Err),
1500+
"expected::value() && requires is_copy_constructible_v<E>");
1501+
static_assert(_LIBCUDACXX_TRAIT(is_move_constructible, _Err),
1502+
"expected::value() && requires is_move_constructible_v<E>");
14841503
if (!this->__has_val_)
14851504
{
14861505
__throw_bad_expected_access<_Err>(_CUDA_VSTD::move(this->__union_.__unex_));

libcudacxx/test/libcudacxx/std/utilities/expected/expected.expected/observers/value.pass.cpp

+92-16
Original file line numberDiff line numberDiff line change
@@ -65,35 +65,111 @@ __host__ __device__ constexpr bool test()
6565
}
6666

6767
#ifndef TEST_HAS_NO_EXCEPTIONS
68-
void test_exceptions()
68+
struct Error
6969
{
70-
// int
70+
enum
7171
{
72-
const cuda::std::expected<int, int> e(cuda::std::unexpect, 5);
73-
try
72+
Default,
73+
MutableRefCalled,
74+
ConstRefCalled,
75+
MutableRvalueCalled,
76+
ConstRvalueCalled
77+
} From = Default;
78+
Error() = default;
79+
Error(const Error& e)
80+
: From(e.From)
81+
{
82+
if (e.From == Default)
7483
{
75-
(void) e.value();
76-
assert(false);
84+
From = ConstRefCalled;
7785
}
78-
catch (const cuda::std::bad_expected_access<int>& ex)
86+
}
87+
Error(Error& e)
88+
: From(e.From)
89+
{
90+
if (e.From == Default)
7991
{
80-
assert(ex.error() == 5);
92+
From = MutableRefCalled;
8193
}
8294
}
83-
84-
// MoveOnly
95+
Error(const Error&& e)
96+
: From(e.From)
8597
{
86-
cuda::std::expected<int, MoveOnly> e(cuda::std::unexpect, 5);
87-
try
98+
if (e.From == Default)
8899
{
89-
(void) cuda::std::move(e).value();
90-
assert(false);
100+
From = ConstRvalueCalled;
91101
}
92-
catch (const cuda::std::bad_expected_access<MoveOnly>& ex)
102+
}
103+
Error(Error&& e)
104+
: From(e.From)
105+
{
106+
if (e.From == Default)
93107
{
94-
assert(ex.error() == 5);
108+
From = MutableRvalueCalled;
95109
}
96110
}
111+
};
112+
113+
void test_exceptions()
114+
{
115+
try
116+
{
117+
const cuda::std::expected<int, int> e(cuda::std::unexpect, 5);
118+
(void) e.value();
119+
assert(false);
120+
}
121+
catch (const cuda::std::bad_expected_access<int>& ex)
122+
{
123+
assert(ex.error() == 5);
124+
}
125+
126+
// Test & overload
127+
try
128+
{
129+
cuda::std::expected<int, Error> e(cuda::std::unexpect);
130+
(void) e.value();
131+
assert(false);
132+
}
133+
catch (const cuda::std::bad_expected_access<Error>& ex)
134+
{
135+
assert(ex.error().From == Error::ConstRefCalled);
136+
}
137+
138+
// Test const& overload
139+
try
140+
{
141+
const cuda::std::expected<int, Error> e(cuda::std::unexpect);
142+
(void) e.value();
143+
assert(false);
144+
}
145+
catch (const cuda::std::bad_expected_access<Error>& ex)
146+
{
147+
assert(ex.error().From == Error::ConstRefCalled);
148+
}
149+
150+
// Test && overload
151+
try
152+
{
153+
cuda::std::expected<int, Error> e(cuda::std::unexpect);
154+
(void) cuda::std::move(e).value();
155+
assert(false);
156+
}
157+
catch (const cuda::std::bad_expected_access<Error>& ex)
158+
{
159+
assert(ex.error().From == Error::MutableRvalueCalled);
160+
}
161+
162+
// Test const&& overload
163+
try
164+
{
165+
const cuda::std::expected<int, Error> e(cuda::std::unexpect);
166+
(void) cuda::std::move(e).value();
167+
assert(false);
168+
}
169+
catch (const cuda::std::bad_expected_access<Error>& ex)
170+
{
171+
assert(ex.error().From == Error::ConstRvalueCalled);
172+
}
97173
}
98174
#endif // !TEST_HAS_NO_EXCEPTIONS
99175

libcudacxx/test/libcudacxx/std/utilities/expected/expected.void/observers/value.pass.cpp

+6-22
Original file line numberDiff line numberDiff line change
@@ -57,32 +57,16 @@ __host__ __device__ constexpr bool test()
5757
#ifndef TEST_HAS_NO_EXCEPTIONS
5858
void test_exceptions()
5959
{
60-
// int
60+
// Test const& overload
61+
try
6162
{
6263
const cuda::std::expected<void, int> e(cuda::std::unexpect, 5);
63-
try
64-
{
65-
e.value();
66-
assert(false);
67-
}
68-
catch (const cuda::std::bad_expected_access<int>& ex)
69-
{
70-
assert(ex.error() == 5);
71-
}
64+
e.value();
65+
assert(false);
7266
}
73-
74-
// MoveOnly
67+
catch (const cuda::std::bad_expected_access<int>& ex)
7568
{
76-
cuda::std::expected<void, MoveOnly> e(cuda::std::unexpect, 5);
77-
try
78-
{
79-
cuda::std::move(e).value();
80-
assert(false);
81-
}
82-
catch (const cuda::std::bad_expected_access<MoveOnly>& ex)
83-
{
84-
assert(ex.error() == 5);
85-
}
69+
assert(ex.error() == 5);
8670
}
8771
}
8872
#endif // !TEST_HAS_NO_EXCEPTIONS

0 commit comments

Comments
 (0)