1 // -*- C++ -*-
2 // Testing utilities for the rvalue reference.
3 //
4 // Copyright (C) 2005-2013 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       bool test __attribute__((unused)) = true;
57       VERIFY( in.valid == true );
58       val = in.val;
59       in.valid = false;
60       valid = true;
61     }
62 
63     rvalstruct&
64     operator=(const rvalstruct&) = delete;
65 
66     rvalstruct&
67     operator=(rvalstruct&& in)
68     {
69       bool test __attribute__((unused)) = true;
70       VERIFY( this != &in );
71       VERIFY( in.valid == true );
72       val = in.val;
73       in.valid = false;
74       valid = true;
75       return *this;
76     }
77   };
78 
79   inline bool
80   operator==(const rvalstruct& lhs, const rvalstruct& rhs)
81   { return lhs.val == rhs.val; }
82 
83   inline bool
84   operator<(const rvalstruct& lhs, const rvalstruct& rhs)
85   { return lhs.val < rhs.val; }
86 
87   void
swap(rvalstruct & lhs,rvalstruct & rhs)88   swap(rvalstruct& lhs, rvalstruct& rhs)
89   {
90     bool test __attribute__((unused)) = true;
91     VERIFY( lhs.valid && rhs.valid );
92     int temp = lhs.val;
93     lhs.val = rhs.val;
94     rhs.val = temp;
95   }
96 
97   // This is a moveable class which copies how many times it is copied.
98   // This is mainly of use in the containers, where the an element inserted
99   // into a container has to be copied once to get there, but we want to check
100   // nothing else is copied.
101   struct copycounter
102   {
103     static int copycount;
104     int val;
105     bool valid;
106 
copycountercopycounter107     copycounter() : val(0), valid(true)
108     { }
109 
copycountercopycounter110     copycounter(int inval) : val(inval), valid(true)
111     { }
112 
copycountercopycounter113     copycounter(const copycounter& in) : val(in.val), valid(true)
114     {
115       bool test __attribute__((unused)) = true;
116       VERIFY( in.valid == true );
117       ++copycount;
118     }
119 
copycountercopycounter120     copycounter(copycounter&& in) noexcept
121     {
122       bool test __attribute__((unused)) = true;
123       VERIFY( in.valid == true );
124       val = in.val;
125       in.valid = false;
126       valid = true;
127     }
128 
129     copycounter&
130     operator=(int newval)
131     {
132       val = newval;
133       valid = true;
134       return *this;
135     }
136 
137     bool
138     operator=(const copycounter& in)
139     {
140       bool test __attribute__((unused)) = true;
141       VERIFY( in.valid == true );
142       ++copycount;
143       val = in.val;
144       valid = true;
145       return true;
146     }
147 
148     copycounter&
149     operator=(copycounter&& in)
150     {
151       bool test __attribute__((unused)) = true;
152       VERIFY(in.valid == true);
153       val = in.val;
154       in.valid = false;
155       valid = true;
156       return *this;
157     }
158 
~copycountercopycounter159     ~copycounter() noexcept
160     { valid = false; }
161   };
162 
163   int copycounter::copycount = 0;
164 
165   inline bool
166   operator==(const copycounter& lhs, const copycounter& rhs)
167   { return lhs.val == rhs.val; }
168 
169   inline bool
170   operator<(const copycounter& lhs, const copycounter& rhs)
171   { return lhs.val < rhs.val; }
172 
173   inline void
swap(copycounter & lhs,copycounter & rhs)174   swap(copycounter& lhs, copycounter& rhs)
175   {
176     bool test __attribute__((unused)) = true;
177     VERIFY( lhs.valid && rhs.valid );
178     int temp = lhs.val;
179     lhs.val = rhs.val;
180     rhs.val = temp;
181   }
182 
183   // In the occasion of libstdc++/48038.
184   struct rvalstruct_compare_by_value
185   {
186     int val;
187     bool ok;
188 
rvalstruct_compare_by_valuervalstruct_compare_by_value189     rvalstruct_compare_by_value(int v)
190     : val(v), ok(true) { }
191 
rvalstruct_compare_by_valuervalstruct_compare_by_value192     rvalstruct_compare_by_value(const rvalstruct_compare_by_value& rh)
193     : val(rh.val), ok(rh.ok)
194     {
195       bool test __attribute__((unused)) = true;
196       VERIFY(rh.ok);
197     }
198 
199     rvalstruct_compare_by_value&
200     operator=(const rvalstruct_compare_by_value& rh)
201     {
202       bool test __attribute__((unused)) = true;
203       VERIFY( rh.ok );
204       val = rh.val;
205       ok = rh.ok;
206       return *this;
207     }
208 
rvalstruct_compare_by_valuervalstruct_compare_by_value209     rvalstruct_compare_by_value(rvalstruct_compare_by_value&& rh)
210     : val(rh.val), ok(rh.ok)
211     {
212       bool test __attribute__((unused)) = true;
213       VERIFY( rh.ok );
214       rh.ok = false;
215     }
216 
217     rvalstruct_compare_by_value&
218     operator=(rvalstruct_compare_by_value&& rh)
219     {
220       bool test __attribute__((unused)) = true;
221       VERIFY( rh.ok );
222       val = rh.val;
223       ok = rh.ok;
224       rh.ok = false;
225       return *this;
226     }
227   };
228 
229   inline bool
230   operator<(rvalstruct_compare_by_value lh,
231 	    rvalstruct_compare_by_value rh)
232   {
233     bool test __attribute__((unused)) = true;
234     VERIFY( rh.ok );
235     VERIFY( lh.ok );
236     return lh.val < rh.val;
237   }
238 
239   inline bool
order(rvalstruct_compare_by_value lh,rvalstruct_compare_by_value rh)240   order(rvalstruct_compare_by_value lh,
241 	rvalstruct_compare_by_value rh)
242   {
243     bool test __attribute__((unused)) = true;
244     VERIFY( rh.ok );
245     VERIFY( lh.ok );
246     return lh.val < rh.val;
247   }
248 
249   struct throwing_move_constructor
250   {
251     throwing_move_constructor() = default;
252 
throwing_move_constructorthrowing_move_constructor253     throwing_move_constructor(throwing_move_constructor&&)
254     { throw 1; }
255 
256     throwing_move_constructor(const throwing_move_constructor&) = default;
257 
258     throwing_move_constructor&
259     operator=(const throwing_move_constructor&) = default;
260   };
261 
262 } // namespace __gnu_test
263 
264 namespace std
265 {
266   /// std::hash specialization for __gnu_test::rvalstruct.
267   template<>
268     struct hash<__gnu_test::rvalstruct>
269     {
270       typedef size_t                    result_type;
271       typedef __gnu_test::rvalstruct  argument_type;
272 
273       size_t
274       operator()(const __gnu_test::rvalstruct& __rvs) const
275       { return __rvs.val; }
276     };
277 }
278 
279 #endif // _GLIBCXX_TESTSUITE_TR1_H
280