1 // -*- C++ -*-
2 // Testing utilities for the rvalue reference.
3 //
4 // Copyright (C) 2005-2019 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3.  If not see
19 // <http://www.gnu.org/licenses/>.
20 //
21 
22 #ifndef _GLIBCXX_TESTSUITE_RVALREF_H
23 #define _GLIBCXX_TESTSUITE_RVALREF_H 1
24 
25 #include <testsuite_hooks.h>
26 #include <bits/functional_hash.h>
27 
28 namespace __gnu_test
29 {
30   // This class is designed to test libstdc++'s template-based rvalue
31   // reference support. It should fail at compile-time if there is an
32   // attempt to copy it.
33   struct rvalstruct
34   {
35     int val;
36     bool valid;
37 
rvalstructrvalstruct38     rvalstruct() : val(0), valid(true)
39     { }
40 
rvalstructrvalstruct41     rvalstruct(int inval) : val(inval), valid(true)
42     { }
43 
44     rvalstruct&
45     operator=(int newval)
46     {
47       val = newval;
48       valid = true;
49       return *this;
50     }
51 
52     rvalstruct(const rvalstruct&) = delete;
53 
rvalstructrvalstruct54     rvalstruct(rvalstruct&& in)
55     {
56       VERIFY( in.valid == true );
57       val = in.val;
58       in.valid = false;
59       valid = true;
60     }
61 
62     rvalstruct&
63     operator=(const rvalstruct&) = delete;
64 
65     rvalstruct&
66     operator=(rvalstruct&& in)
67     {
68       VERIFY( this != &in );
69       VERIFY( in.valid == true );
70       val = in.val;
71       in.valid = false;
72       valid = true;
73       return *this;
74     }
75   };
76 
77   inline bool
78   operator==(const rvalstruct& lhs, const rvalstruct& rhs)
79   { return lhs.val == rhs.val; }
80 
81   inline bool
82   operator<(const rvalstruct& lhs, const rvalstruct& rhs)
83   { return lhs.val < rhs.val; }
84 
85   void
swap(rvalstruct & lhs,rvalstruct & rhs)86   swap(rvalstruct& lhs, rvalstruct& rhs)
87   {
88     VERIFY( lhs.valid && rhs.valid );
89     int temp = lhs.val;
90     lhs.val = rhs.val;
91     rhs.val = temp;
92   }
93 
94   // This is a moveable class which copies how many times it is copied.
95   // This is mainly of use in the containers, where the an element inserted
96   // into a container has to be copied once to get there, but we want to check
97   // nothing else is copied.
98   struct copycounter
99   {
100     static int copycount;
101     int val;
102     bool valid;
103 
copycountercopycounter104     copycounter() : val(0), valid(true)
105     { }
106 
copycountercopycounter107     copycounter(int inval) : val(inval), valid(true)
108     { }
109 
copycountercopycounter110     copycounter(const copycounter& in) : val(in.val), valid(true)
111     {
112       VERIFY( in.valid == true );
113       ++copycount;
114     }
115 
copycountercopycounter116     copycounter(copycounter&& in) noexcept
117     {
118       VERIFY( in.valid == true );
119       val = in.val;
120       in.valid = false;
121       valid = true;
122     }
123 
124     copycounter&
125     operator=(int newval)
126     {
127       val = newval;
128       valid = true;
129       return *this;
130     }
131 
132     bool
133     operator=(const copycounter& in)
134     {
135       VERIFY( in.valid == true );
136       ++copycount;
137       val = in.val;
138       valid = true;
139       return true;
140     }
141 
142     copycounter&
143     operator=(copycounter&& in)
144     {
145       VERIFY(in.valid == true);
146       val = in.val;
147       in.valid = false;
148       valid = true;
149       return *this;
150     }
151 
~copycountercopycounter152     ~copycounter() noexcept
153     { valid = false; }
154   };
155 
156   int copycounter::copycount = 0;
157 
158   inline bool
159   operator==(const copycounter& lhs, const copycounter& rhs)
160   { return lhs.val == rhs.val; }
161 
162   inline bool
163   operator<(const copycounter& lhs, const copycounter& rhs)
164   { return lhs.val < rhs.val; }
165 
166   inline void
swap(copycounter & lhs,copycounter & rhs)167   swap(copycounter& lhs, copycounter& rhs)
168   {
169     VERIFY( lhs.valid && rhs.valid );
170     int temp = lhs.val;
171     lhs.val = rhs.val;
172     rhs.val = temp;
173   }
174 
175   // In the occasion of libstdc++/48038.
176   struct rvalstruct_compare_by_value
177   {
178     int val;
179     bool ok;
180 
rvalstruct_compare_by_valuervalstruct_compare_by_value181     rvalstruct_compare_by_value(int v)
182     : val(v), ok(true) { }
183 
rvalstruct_compare_by_valuervalstruct_compare_by_value184     rvalstruct_compare_by_value(const rvalstruct_compare_by_value& rh)
185     : val(rh.val), ok(rh.ok)
186     {
187       VERIFY(rh.ok);
188     }
189 
190     rvalstruct_compare_by_value&
191     operator=(const rvalstruct_compare_by_value& rh)
192     {
193       VERIFY( rh.ok );
194       val = rh.val;
195       ok = rh.ok;
196       return *this;
197     }
198 
rvalstruct_compare_by_valuervalstruct_compare_by_value199     rvalstruct_compare_by_value(rvalstruct_compare_by_value&& rh)
200     : val(rh.val), ok(rh.ok)
201     {
202       VERIFY( rh.ok );
203       rh.ok = false;
204     }
205 
206     rvalstruct_compare_by_value&
207     operator=(rvalstruct_compare_by_value&& rh)
208     {
209       VERIFY( rh.ok );
210       val = rh.val;
211       ok = rh.ok;
212       rh.ok = false;
213       return *this;
214     }
215   };
216 
217   inline bool
218   operator<(rvalstruct_compare_by_value lh,
219 	    rvalstruct_compare_by_value rh)
220   {
221     VERIFY( rh.ok );
222     VERIFY( lh.ok );
223     return lh.val < rh.val;
224   }
225 
226   inline bool
order(rvalstruct_compare_by_value lh,rvalstruct_compare_by_value rh)227   order(rvalstruct_compare_by_value lh,
228 	rvalstruct_compare_by_value rh)
229   {
230     VERIFY( rh.ok );
231     VERIFY( lh.ok );
232     return lh.val < rh.val;
233   }
234 
235   struct throwing_move_constructor
236   {
237     throwing_move_constructor() = default;
238 
throwing_move_constructorthrowing_move_constructor239     throwing_move_constructor(throwing_move_constructor&&)
240     { throw 1; }
241 
242     throwing_move_constructor(const throwing_move_constructor&) = default;
243 
244     throwing_move_constructor&
245     operator=(const throwing_move_constructor&) = default;
246   };
247 
248 } // namespace __gnu_test
249 
250 namespace std
251 {
252   /// std::hash specialization for __gnu_test::rvalstruct.
253   template<>
254     struct hash<__gnu_test::rvalstruct>
255     {
256       typedef size_t                    result_type;
257       typedef __gnu_test::rvalstruct  argument_type;
258 
259       size_t
260       operator()(const __gnu_test::rvalstruct& __rvs) const
261       { return __rvs.val; }
262     };
263 }
264 
265 #endif // _GLIBCXX_TESTSUITE_TR1_H
266