1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // <tuple>
10
11 // template <class... Types> class tuple;
12
13 // template <class... UTypes>
14 // tuple& operator=(const tuple<UTypes...>& u);
15
16 // UNSUPPORTED: c++03
17
18 #include <tuple>
19 #include <array>
20 #include <string>
21 #include <utility>
22 #include <cassert>
23
24 #include "propagate_value_category.hpp"
25
26 struct TracksIntQuals {
TracksIntQualsTracksIntQuals27 TracksIntQuals() : value(-1), value_category(VC_None), assigned(false) {}
28
29 template <class Tp,
30 class = typename std::enable_if<!std::is_same<
31 typename std::decay<Tp>::type, TracksIntQuals>::value>::type>
TracksIntQualsTracksIntQuals32 TracksIntQuals(Tp &&x)
33 : value(x), value_category(getValueCategory<Tp &&>()), assigned(false) {
34 static_assert(std::is_same<UnCVRef<Tp>, int>::value, "");
35 }
36
37 template <class Tp,
38 class = typename std::enable_if<!std::is_same<
39 typename std::decay<Tp>::type, TracksIntQuals>::value>::type>
operator =TracksIntQuals40 TracksIntQuals &operator=(Tp &&x) {
41 static_assert(std::is_same<UnCVRef<Tp>, int>::value, "");
42 value = x;
43 value_category = getValueCategory<Tp &&>();
44 assigned = true;
45 return *this;
46 }
47
resetTracksIntQuals48 void reset() {
49 value = -1;
50 value_category = VC_None;
51 assigned = false;
52 }
53
checkConstructTracksIntQuals54 bool checkConstruct(int expect, ValueCategory expect_vc) const {
55 return value != 1 && value == expect && value_category == expect_vc &&
56 assigned == false;
57 }
58
checkAssignTracksIntQuals59 bool checkAssign(int expect, ValueCategory expect_vc) const {
60 return value != 1 && value == expect && value_category == expect_vc &&
61 assigned == true;
62 }
63
64 int value;
65 ValueCategory value_category;
66 bool assigned;
67 };
68
69 template <class Tup>
70 struct DerivedFromTup : Tup {
71 using Tup::Tup;
72 };
73
74 template <ValueCategory VC>
do_derived_assign_test()75 void do_derived_assign_test() {
76 using Tup1 = std::tuple<long, TracksIntQuals>;
77 Tup1 t;
78 auto reset = [&]() {
79 std::get<0>(t) = -1;
80 std::get<1>(t).reset();
81 };
82 {
83 DerivedFromTup<std::tuple<int, int>> d;
84 std::get<0>(d) = 42;
85 std::get<1>(d) = 101;
86
87 t = ValueCategoryCast<VC>(d);
88 assert(std::get<0>(t) == 42);
89 assert(std::get<1>(t).checkAssign(101, VC));
90 }
91 reset();
92 {
93 DerivedFromTup<std::pair<int, int>> d;
94 std::get<0>(d) = 42;
95 std::get<1>(d) = 101;
96
97 t = ValueCategoryCast<VC>(d);
98 assert(std::get<0>(t) == 42);
99 assert(std::get<1>(t).checkAssign(101, VC));
100 }
101 reset();
102 {
103 #ifdef _LIBCPP_VERSION // assignment from std::array is a libc++ extension
104 DerivedFromTup<std::array<int, 2>> d;
105 std::get<0>(d) = 42;
106 std::get<1>(d) = 101;
107
108 t = ValueCategoryCast<VC>(d);
109 assert(std::get<0>(t) == 42);
110 assert(std::get<1>(t).checkAssign(101, VC));
111 #endif
112 }
113 }
114
main(int,char **)115 int main(int, char**) {
116 do_derived_assign_test<VC_LVal | VC_Const>();
117 do_derived_assign_test<VC_RVal>();
118
119 return 0;
120 }
121