1 // Copyright (C) 2013-2020 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3.  If not see
16 // <http://www.gnu.org/licenses/>.
17 
18 namespace cons_value {
19 
20 struct tracker
21 {
trackercons_value::tracker22   tracker(int value) : value(value) { ++count; }
~trackercons_value::tracker23   ~tracker() { --count; }
24 
trackercons_value::tracker25   tracker(tracker const& other) : value(other.value) { ++count; }
trackercons_value::tracker26   tracker(tracker&& other) : value(other.value)
27   {
28     other.value = -1;
29     ++count;
30   }
31 
32   tracker& operator=(tracker const&) = default;
33   tracker& operator=(tracker&&) = default;
34 
35   int value;
36 
37   static int count;
38 };
39 
40 int tracker::count = 0;
41 
42 struct exception { };
43 
44 struct throwing_construction
45 {
throwing_constructioncons_value::throwing_construction46   explicit throwing_construction(bool propagate) : propagate(propagate) { }
47 
throwing_constructioncons_value::throwing_construction48   throwing_construction(throwing_construction const& other)
49   : propagate(other.propagate)
50   {
51     if(propagate)
52       throw exception {};
53   }
54 
55   bool propagate;
56 };
57 
58 static void
test()59 test ()
60 {
61   // [20.5.4.1] Constructors
62 
63   {
64     auto i = 0x1234ABCD;
65     gdb::optional<long> o { i };
66     VERIFY( o );
67     VERIFY( *o == 0x1234ABCD );
68     VERIFY( i == 0x1234ABCD );
69   }
70 
71   {
72     auto i = 0x1234ABCD;
73     gdb::optional<long> o = i;
74     VERIFY( o );
75     VERIFY( *o == 0x1234ABCD );
76     VERIFY( i == 0x1234ABCD );
77   }
78 
79   {
80     auto i = 0x1234ABCD;
81     gdb::optional<long> o = { i };
82     VERIFY( o );
83     VERIFY( *o == 0x1234ABCD );
84     VERIFY( i == 0x1234ABCD );
85   }
86 
87   {
88     auto i = 0x1234ABCD;
89     gdb::optional<long> o { std::move(i) };
90     VERIFY( o );
91     VERIFY( *o == 0x1234ABCD );
92     VERIFY( i == 0x1234ABCD );
93   }
94 
95   {
96     auto i = 0x1234ABCD;
97     gdb::optional<long> o = std::move(i);
98     VERIFY( o );
99     VERIFY( *o == 0x1234ABCD );
100     VERIFY( i == 0x1234ABCD );
101   }
102 
103   {
104     auto i = 0x1234ABCD;
105     gdb::optional<long> o = { std::move(i) };
106     VERIFY( o );
107     VERIFY( *o == 0x1234ABCD );
108     VERIFY( i == 0x1234ABCD );
109   }
110 
111 #ifndef GDB_OPTIONAL
112   {
113     std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
114     gdb::optional<std::vector<int>> o { v };
115     VERIFY( !v.empty() );
116     VERIFY( o->size() == 6 );
117   }
118 #endif
119 
120   {
121     std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
122     gdb::optional<std::vector<int>> o = v;
123     VERIFY( !v.empty() );
124     VERIFY( o->size() == 6 );
125   }
126 
127   {
128     std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
129     gdb::optional<std::vector<int>> o { v };
130     VERIFY( !v.empty() );
131     VERIFY( o->size() == 6 );
132   }
133 
134   {
135     std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
136     gdb::optional<std::vector<int>> o { std::move(v) };
137     VERIFY( v.empty() );
138     VERIFY( o->size() == 6 );
139   }
140 
141   {
142     std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
143     gdb::optional<std::vector<int>> o = std::move(v);
144     VERIFY( v.empty() );
145     VERIFY( o->size() == 6 );
146   }
147 
148   {
149     std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
150     gdb::optional<std::vector<int>> o { std::move(v) };
151     VERIFY( v.empty() );
152     VERIFY( o->size() == 6 );
153   }
154 
155   {
156     tracker t { 333 };
157     gdb::optional<tracker> o = t;
158     VERIFY( o->value == 333 );
159     VERIFY( tracker::count == 2 );
160     VERIFY( t.value == 333 );
161   }
162 
163   {
164     tracker t { 333 };
165     gdb::optional<tracker> o = std::move(t);
166     VERIFY( o->value == 333 );
167     VERIFY( tracker::count == 2 );
168     VERIFY( t.value == -1 );
169   }
170 
171   enum outcome { nothrow, caught, bad_catch };
172 
173   {
174     outcome result = nothrow;
175     throwing_construction t { false };
176 
177     try
178     {
179       gdb::optional<throwing_construction> o { t };
180     }
181     catch(exception const&)
182     { result = caught; }
183     catch(...)
184     { result = bad_catch; }
185 
186     VERIFY( result == nothrow );
187   }
188 
189   {
190     outcome result = nothrow;
191     throwing_construction t { true };
192 
193     try
194     {
195       gdb::optional<throwing_construction> o { t };
196     }
197     catch(exception const&)
198     { result = caught; }
199     catch(...)
200     { result = bad_catch; }
201 
202     VERIFY( result == caught );
203   }
204 
205   {
206     outcome result = nothrow;
207     throwing_construction t { false };
208 
209     try
210     {
211       gdb::optional<throwing_construction> o { std::move(t) };
212     }
213     catch(exception const&)
214     { result = caught; }
215     catch(...)
216     { result = bad_catch; }
217 
218     VERIFY( result == nothrow );
219   }
220 
221   {
222     outcome result = nothrow;
223     throwing_construction t { true };
224 
225     try
226     {
227       gdb::optional<throwing_construction> o { std::move(t) };
228     }
229     catch(exception const&)
230     { result = caught; }
231     catch(...)
232     { result = bad_catch; }
233 
234     VERIFY( result == caught );
235   }
236 
237   {
238 #ifndef GDB_OPTIONAL
239     gdb::optional<std::string> os = "foo";
240 #endif
241     struct X
242     {
243       explicit X(int) {}
244       X& operator=(int) {return *this;}
245     };
246 #ifndef GDB_OPTIONAL
247     gdb::optional<X> ox{42};
248 #endif
249     gdb::optional<int> oi{42};
250 #ifndef GDB_OPTIONAL
251     gdb::optional<X> ox2{oi};
252 #endif
253     gdb::optional<std::string> os2;
254     os2 = "foo";
255 #ifndef GDB_OPTIONAL
256     gdb::optional<X> ox3;
257     ox3 = 42;
258     gdb::optional<X> ox4;
259     ox4 = oi;
260 #endif
261   }
262   {
263     // no converting construction.
264 #ifndef GDB_OPTIONAL
265     gdb::optional<int> oi = gdb::optional<short>();
266     VERIFY(!bool(oi));
267     gdb::optional<std::string> os = gdb::optional<const char*>();
268     VERIFY(!bool(os));
269 #endif
270     gdb::optional<gdb::optional<int>> ooi = gdb::optional<int>();
271     VERIFY(bool(ooi));
272     ooi = gdb::optional<int>();
273     VERIFY(bool(ooi));
274     ooi = gdb::optional<int>(42);
275     VERIFY(bool(ooi));
276     VERIFY(bool(*ooi));
277 #ifndef GDB_OPTIONAL
278     gdb::optional<gdb::optional<int>> ooi2 = gdb::optional<short>();
279     VERIFY(bool(ooi2));
280     ooi2 = gdb::optional<short>();
281     VERIFY(bool(ooi2));
282     ooi2 = gdb::optional<short>(6);
283     VERIFY(bool(ooi2));
284     VERIFY(bool(*ooi2));
285     gdb::optional<gdb::optional<int>> ooi3 = gdb::optional<int>(42);
286     VERIFY(bool(ooi3));
287     VERIFY(bool(*ooi3));
288     gdb::optional<gdb::optional<int>> ooi4 = gdb::optional<short>(6);
289     VERIFY(bool(ooi4));
290     VERIFY(bool(*ooi4));
291 #endif
292   }
293 }
294 
295 } // namespace cons_value
296