1// -*- C++ -*-
2// Testing utilities for the rvalue reference.
3//
4// Copyright (C) 2005-2015 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
28namespace __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
38    rvalstruct() : val(0), valid(true)
39    { }
40
41    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
54    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
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
107    copycounter() : val(0), valid(true)
108    { }
109
110    copycounter(int inval) : val(inval), valid(true)
111    { }
112
113    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
120    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
159    ~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
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
189    rvalstruct_compare_by_value(int v)
190    : val(v), ok(true) { }
191
192    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
209    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
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
253    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
264namespace 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