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