1// { dg-options "-std=gnu++14" }
2// { dg-do run }
3
4// Copyright (C) 2013-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 moved_to 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#include <experimental/optional>
22#include <testsuite_hooks.h>
23
24#include <vector>
25
26struct tracker
27{
28  tracker(int value) : value(value) { ++count; }
29  ~tracker() { --count; }
30
31  tracker(tracker const& other) : value(other.value) { ++count; }
32  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
46int tracker::count = 0;
47
48struct exception { };
49
50struct throwing_construction
51{
52  explicit throwing_construction(bool propagate) : propagate(propagate) { }
53
54  throwing_construction(throwing_construction const& other)
55  : propagate(other.propagate)
56  {
57    if(propagate)
58      throw exception {};
59  }
60
61  bool propagate;
62};
63
64int 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