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