Skip to content

Commit d28d6b1

Browse files
committed
assign
1 parent 2854f9f commit d28d6b1

File tree

6 files changed

+414
-357
lines changed

6 files changed

+414
-357
lines changed

libcxx/include/variant

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ protected:
925925
}
926926

927927
template <class _That>
928-
_LIBCPP_HIDE_FROM_ABI void __generic_assign(_That&& __that) {
928+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __generic_assign(_That&& __that) {
929929
if (this->valueless_by_exception() && __that.valueless_by_exception()) {
930930
// do nothing.
931931
} else if (__that.valueless_by_exception()) {
@@ -962,19 +962,21 @@ class _LIBCPP_TEMPLATE_VIS __move_assignment;
962962
move_assignment \
963963
}
964964

965-
_LIBCPP_VARIANT_MOVE_ASSIGNMENT(_Trait::_TriviallyAvailable,
966-
__move_assignment& operator=(__move_assignment&& __that) = default;);
965+
_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
966+
_Trait::_TriviallyAvailable,
967+
_LIBCPP_CONSTEXPR_SINCE_CXX20 __move_assignment& operator=(__move_assignment&& __that) = default;);
967968

968969
_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
969970
_Trait::_Available,
970-
__move_assignment&
971+
_LIBCPP_CONSTEXPR_SINCE_CXX20 __move_assignment&
971972
operator=(__move_assignment&& __that) noexcept(
972973
__all<(is_nothrow_move_constructible_v<_Types> && is_nothrow_move_assignable_v<_Types>)...>::value) {
973974
this->__generic_assign(std::move(__that));
974975
return *this;
975976
});
976977

977-
_LIBCPP_VARIANT_MOVE_ASSIGNMENT(_Trait::_Unavailable, __move_assignment& operator=(__move_assignment&&) = delete;);
978+
_LIBCPP_VARIANT_MOVE_ASSIGNMENT(
979+
_Trait::_Unavailable, _LIBCPP_CONSTEXPR_SINCE_CXX20 __move_assignment& operator=(__move_assignment&&) = delete;);
978980

979981
# undef _LIBCPP_VARIANT_MOVE_ASSIGNMENT
980982

@@ -997,16 +999,19 @@ class _LIBCPP_TEMPLATE_VIS __copy_assignment;
997999
copy_assignment __copy_assignment& operator=(__copy_assignment&&) = default; \
9981000
}
9991001

1000-
_LIBCPP_VARIANT_COPY_ASSIGNMENT(_Trait::_TriviallyAvailable,
1001-
__copy_assignment& operator=(const __copy_assignment& __that) = default;);
1002+
_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1003+
_Trait::_TriviallyAvailable,
1004+
_LIBCPP_CONSTEXPR_SINCE_CXX20 __copy_assignment& operator=(const __copy_assignment& __that) = default;);
10021005

10031006
_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1004-
_Trait::_Available, __copy_assignment& operator=(const __copy_assignment& __that) {
1007+
_Trait::_Available, _LIBCPP_CONSTEXPR_SINCE_CXX20 __copy_assignment& operator=(const __copy_assignment& __that) {
10051008
this->__generic_assign(__that);
10061009
return *this;
10071010
});
10081011

1009-
_LIBCPP_VARIANT_COPY_ASSIGNMENT(_Trait::_Unavailable, __copy_assignment& operator=(const __copy_assignment&) = delete;);
1012+
_LIBCPP_VARIANT_COPY_ASSIGNMENT(
1013+
_Trait::_Unavailable,
1014+
_LIBCPP_CONSTEXPR_SINCE_CXX20 __copy_assignment& operator=(const __copy_assignment&) = delete;);
10101015

10111016
# undef _LIBCPP_VARIANT_COPY_ASSIGNMENT
10121017

@@ -1022,11 +1027,11 @@ public:
10221027
_LIBCPP_HIDE_FROM_ABI __impl& operator=(__impl&&) = default;
10231028

10241029
template <size_t _Ip, class _Arg>
1025-
_LIBCPP_HIDE_FROM_ABI void __assign(_Arg&& __arg) {
1030+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign(_Arg&& __arg) {
10261031
this->__assign_alt(__access::__base::__get_alt<_Ip>(*this), std::forward<_Arg>(__arg));
10271032
}
10281033

1029-
inline _LIBCPP_HIDE_FROM_ABI void __swap(__impl& __that) {
1034+
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void __swap(__impl& __that) {
10301035
if (this->valueless_by_exception() && __that.valueless_by_exception()) {
10311036
// do nothing.
10321037
} else if (this->index() == __that.index()) {
@@ -1071,7 +1076,7 @@ public:
10711076
}
10721077

10731078
private:
1074-
inline _LIBCPP_HIDE_FROM_ABI bool __move_nothrow() const {
1079+
constexpr inline _LIBCPP_HIDE_FROM_ABI bool __move_nothrow() const {
10751080
constexpr bool __results[] = {is_nothrow_move_constructible_v<_Types>...};
10761081
return this->valueless_by_exception() || __results[this->index()];
10771082
}
@@ -1235,7 +1240,7 @@ public:
12351240
_Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, initializer_list< _Up>&, _Args...>)
12361241
: __impl_(in_place_index<_Ip>, __il, std::forward<_Args>(__args)...) {}
12371242

1238-
_LIBCPP_HIDE_FROM_ABI ~variant() = default;
1243+
_LIBCPP_HIDE_FROM_ABI constexpr ~variant() = default;
12391244

12401245
_LIBCPP_HIDE_FROM_ABI constexpr variant& operator=(const variant&) = default;
12411246
_LIBCPP_HIDE_FROM_ABI constexpr variant& operator=(variant&&) = default;
@@ -1245,7 +1250,7 @@ public:
12451250
class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>,
12461251
size_t _Ip = __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
12471252
enable_if_t<is_assignable_v<_Tp&, _Arg> && is_constructible_v<_Tp, _Arg>, int> = 0>
1248-
_LIBCPP_HIDE_FROM_ABI variant&
1253+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI variant&
12491254
operator=(_Arg&& __arg) noexcept(is_nothrow_assignable_v<_Tp&, _Arg> && is_nothrow_constructible_v<_Tp, _Arg>) {
12501255
__impl_.template __assign<_Ip>(std::forward<_Arg>(__arg));
12511256
return *this;
@@ -1297,7 +1302,7 @@ public:
12971302
enable_if_t< __all<(__dependent_type<is_move_constructible<_Types>, _Dummy>::value &&
12981303
__dependent_type<is_swappable<_Types>, _Dummy>::value)...>::value,
12991304
int> = 0>
1300-
_LIBCPP_HIDE_FROM_ABI void swap(variant& __that) noexcept(
1305+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(variant& __that) noexcept(
13011306
__all<(is_nothrow_move_constructible_v<_Types> && is_nothrow_swappable_v<_Types>)...>::value) {
13021307
__impl_.__swap(__that.__impl_);
13031308
}

libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ struct Dummy {
3333

3434
struct ThrowsCtorT {
3535
ThrowsCtorT(int) noexcept(false) {}
36-
ThrowsCtorT &operator=(int) noexcept { return *this; }
36+
ThrowsCtorT& operator=(int) noexcept { return *this; }
3737
};
3838

3939
struct ThrowsAssignT {
4040
ThrowsAssignT(int) noexcept {}
41-
ThrowsAssignT &operator=(int) noexcept(false) { return *this; }
41+
ThrowsAssignT& operator=(int) noexcept(false) { return *this; }
4242
};
4343

4444
struct NoThrowT {
4545
NoThrowT(int) noexcept {}
46-
NoThrowT &operator=(int) noexcept { return *this; }
46+
NoThrowT& operator=(int) noexcept { return *this; }
4747
};
4848

4949
} // namespace MetaHelpers
@@ -55,7 +55,7 @@ struct ThrowsCtorT {
5555
int value;
5656
ThrowsCtorT() : value(0) {}
5757
ThrowsCtorT(int) noexcept(false) { throw 42; }
58-
ThrowsCtorT &operator=(int v) noexcept {
58+
ThrowsCtorT& operator=(int v) noexcept {
5959
value = v;
6060
return *this;
6161
}
@@ -64,9 +64,12 @@ struct ThrowsCtorT {
6464
struct MoveCrashes {
6565
int value;
6666
MoveCrashes(int v = 0) noexcept : value{v} {}
67-
MoveCrashes(MoveCrashes &&) noexcept { assert(false); }
68-
MoveCrashes &operator=(MoveCrashes &&) noexcept { assert(false); return *this; }
69-
MoveCrashes &operator=(int v) noexcept {
67+
MoveCrashes(MoveCrashes&&) noexcept { assert(false); }
68+
MoveCrashes& operator=(MoveCrashes&&) noexcept {
69+
assert(false);
70+
return *this;
71+
}
72+
MoveCrashes& operator=(int v) noexcept {
7073
value = v;
7174
return *this;
7275
}
@@ -76,8 +79,8 @@ struct ThrowsCtorTandMove {
7679
int value;
7780
ThrowsCtorTandMove() : value(0) {}
7881
ThrowsCtorTandMove(int) noexcept(false) { throw 42; }
79-
ThrowsCtorTandMove(ThrowsCtorTandMove &&) noexcept(false) { assert(false); }
80-
ThrowsCtorTandMove &operator=(int v) noexcept {
82+
ThrowsCtorTandMove(ThrowsCtorTandMove&&) noexcept(false) { assert(false); }
83+
ThrowsCtorTandMove& operator=(int v) noexcept {
8184
value = v;
8285
return *this;
8386
}
@@ -87,14 +90,14 @@ struct ThrowsAssignT {
8790
int value;
8891
ThrowsAssignT() : value(0) {}
8992
ThrowsAssignT(int v) noexcept : value(v) {}
90-
ThrowsAssignT &operator=(int) noexcept(false) { throw 42; }
93+
ThrowsAssignT& operator=(int) noexcept(false) { throw 42; }
9194
};
9295

9396
struct NoThrowT {
9497
int value;
9598
NoThrowT() : value(0) {}
9699
NoThrowT(int v) noexcept : value(v) {}
97-
NoThrowT &operator=(int v) noexcept {
100+
NoThrowT& operator=(int v) noexcept {
98101
value = v;
99102
return *this;
100103
}
@@ -126,29 +129,25 @@ void test_T_assignment_sfinae() {
126129
}
127130
{
128131
using V = std::variant<std::string, std::string>;
129-
static_assert(!std::is_assignable<V, const char *>::value, "ambiguous");
132+
static_assert(!std::is_assignable<V, const char*>::value, "ambiguous");
130133
}
131134
{
132-
using V = std::variant<std::string, void *>;
135+
using V = std::variant<std::string, void*>;
133136
static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
134137
}
135138
{
136139
using V = std::variant<std::string, float>;
137-
static_assert(std::is_assignable<V, int>::value == VariantAllowsNarrowingConversions,
138-
"no matching operator=");
140+
static_assert(std::is_assignable<V, int>::value == VariantAllowsNarrowingConversions, "no matching operator=");
139141
}
140142
{
141143
using V = std::variant<std::unique_ptr<int>, bool>;
142-
static_assert(!std::is_assignable<V, std::unique_ptr<char>>::value,
143-
"no explicit bool in operator=");
144+
static_assert(!std::is_assignable<V, std::unique_ptr<char>>::value, "no explicit bool in operator=");
144145
struct X {
145146
operator void*();
146147
};
147-
static_assert(!std::is_assignable<V, X>::value,
148-
"no boolean conversion in operator=");
148+
static_assert(!std::is_assignable<V, X>::value, "no boolean conversion in operator=");
149149
#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
150-
static_assert(std::is_assignable<V, std::false_type>::value,
151-
"converted to bool in operator=");
150+
static_assert(std::is_assignable<V, std::false_type>::value, "converted to bool in operator=");
152151
#endif
153152
}
154153
{
@@ -157,22 +156,21 @@ void test_T_assignment_sfinae() {
157156
operator X();
158157
};
159158
using V = std::variant<X>;
160-
static_assert(std::is_assignable<V, Y>::value,
161-
"regression on user-defined conversions in operator=");
159+
static_assert(std::is_assignable<V, Y>::value, "regression on user-defined conversions in operator=");
162160
}
163161
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
164162
{
165-
using V = std::variant<int, int &&>;
163+
using V = std::variant<int, int&&>;
166164
static_assert(!std::is_assignable<V, int>::value, "ambiguous");
167165
}
168166
{
169-
using V = std::variant<int, const int &>;
167+
using V = std::variant<int, const int&>;
170168
static_assert(!std::is_assignable<V, int>::value, "ambiguous");
171169
}
172170
#endif // TEST_VARIANT_HAS_NO_REFERENCES
173171
}
174172

175-
void test_T_assignment_basic() {
173+
TEST_CONSTEXPR_CXX20 bool test_T_assignment_basic() {
176174
{
177175
std::variant<int> v(43);
178176
v = 42;
@@ -201,35 +199,18 @@ void test_T_assignment_basic() {
201199
#endif
202200
{
203201
std::variant<std::string, bool> v = true;
204-
v = "bar";
202+
v = "bar";
205203
assert(v.index() == 0);
206204
assert(std::get<0>(v) == "bar");
207205
}
208-
{
209-
std::variant<bool, std::unique_ptr<int>> v;
210-
v = nullptr;
211-
assert(v.index() == 1);
212-
assert(std::get<1>(v) == nullptr);
213-
}
214-
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
215-
{
216-
using V = std::variant<int &, int &&, long>;
217-
int x = 42;
218-
V v(43l);
219-
v = x;
220-
assert(v.index() == 0);
221-
assert(&std::get<0>(v) == &x);
222-
v = std::move(x);
223-
assert(v.index() == 1);
224-
assert(&std::get<1>(v) == &x);
225-
// 'long' is selected by FUN(const int &) since 'const int &' cannot bind
226-
// to 'int&'.
227-
const int &cx = x;
228-
v = cx;
229-
assert(v.index() == 2);
230-
assert(std::get<2>(v) == 42);
231-
}
232-
#endif // TEST_VARIANT_HAS_NO_REFERENCES
206+
return true;
207+
}
208+
209+
void test_T_assignment_basic_no_constexpr() {
210+
std::variant<bool, std::unique_ptr<int>> v;
211+
v = nullptr;
212+
assert(v.index() == 1);
213+
assert(std::get<1>(v) == nullptr);
233214
}
234215

235216
void test_T_assignment_performs_construction() {
@@ -298,23 +279,29 @@ void test_T_assignment_performs_assignment() {
298279
#endif // TEST_HAS_NO_EXCEPTIONS
299280
}
300281

301-
void test_T_assignment_vector_bool() {
282+
TEST_CONSTEXPR_CXX20 bool test_T_assignment_vector_bool() {
302283
#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
303284
std::vector<bool> vec = {true};
304285
std::variant<bool, int> v;
305286
v = vec[0];
306287
assert(v.index() == 0);
307288
assert(std::get<0>(v) == true);
308289
#endif
290+
return true;
309291
}
310292

311293
int main(int, char**) {
312294
test_T_assignment_basic();
295+
test_T_assignment_basic_no_constexpr();
313296
test_T_assignment_performs_construction();
314297
test_T_assignment_performs_assignment();
315298
test_T_assignment_noexcept();
316299
test_T_assignment_sfinae();
317300
test_T_assignment_vector_bool();
318301

302+
#if TEST_STD_VER >= 20
303+
static_assert(test_T_assignment_basic());
304+
static_assert(test_T_assignment_vector_bool());
305+
#endif
319306
return 0;
320307
}

0 commit comments

Comments
 (0)