1 // { dg-options "-std=gnu++1y" }
2 // { dg-do run }
3 
4 // Copyright (C) 2013-2014 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 <tuple>
25 
26 struct trivially_destructible
27 {
28   trivially_destructible() = delete;
29   trivially_destructible(trivially_destructible const&) = delete;
30   trivially_destructible& operator=(trivially_destructible const&) = delete;
31   trivially_destructible(trivially_destructible&&) = delete;
32   trivially_destructible& operator=(trivially_destructible&&) = delete;
33   ~trivially_destructible() noexcept = default;
34 };
35 
36 static_assert( std::is_trivially_destructible<trivially_destructible>(), "" );
37 
38 struct no_default_constructor
39 {
40   no_default_constructor() = delete;
41 };
42 
43 struct no_copy_constructor
44 {
45   no_copy_constructor() = default;
46   no_copy_constructor(no_copy_constructor const&) = delete;
47   no_copy_constructor& operator=(no_copy_constructor const&) = default;
48   no_copy_constructor(no_copy_constructor&&) = default;
49   no_copy_constructor& operator=(no_copy_constructor&&) = default;
50 };
51 
52 struct no_copy_assignment
53 {
54   no_copy_assignment() = default;
55   no_copy_assignment(no_copy_assignment const&) = default;
56   no_copy_assignment(no_copy_assignment&&) = default;
57   no_copy_assignment& operator=(no_copy_assignment&&) = default;
58 };
59 
60 struct no_move_constructor
61 {
62   no_move_constructor() = default;
63   no_move_constructor(no_move_constructor const&) = default;
64   no_move_constructor& operator=(no_move_constructor const&) = default;
65   no_move_constructor(no_move_constructor&&) = delete;
66   no_move_constructor& operator=(no_move_constructor&&) = default;
67 };
68 
69 struct no_move_assignment
70 {
71   no_move_assignment() = default;
72   no_move_assignment(no_move_assignment const&) = default;
73   no_move_assignment& operator=(no_move_assignment const&) = default;
74   no_move_assignment(no_move_assignment&&) = default;
75   no_move_assignment& operator=(no_move_assignment&&) = delete;
76 };
77 
78 struct no_copy : no_copy_constructor, no_copy_assignment { };
79 struct no_move : no_move_constructor, no_move_assignment { };
80 
81 // Laxest possible model of a value type for optional
82 struct only_destructible
83 {
84   only_destructible(only_destructible&&) = delete;
85 };
86 
main()87 int main()
88 {
89   {
90     static_assert( std::is_trivially_destructible<std::experimental::optional<trivially_destructible>>(), "" );
91   }
92 
93   {
94     using T = no_default_constructor;
95     using O = std::experimental::optional<T>;
96     static_assert( std::is_same<O::value_type, T>(), "" );
97     static_assert( std::is_default_constructible<O>(), "" );
98     { O o; }
99     static_assert( std::is_copy_constructible<O>(), "" );
100     { O o; auto copy = o; }
101     static_assert( std::is_copy_assignable<O>(), "" );
102     { O o, p; p = o; }
103     static_assert( std::is_move_constructible<O>(), "" );
104     { O o; auto moved_to = std::move(o); }
105     static_assert( std::is_move_assignable<O>(), "" );
106     { O o, p; p = std::move(o); }
107   }
108 
109   {
110     using T = no_copy_constructor;
111     using O = std::experimental::optional<T>;
112     static_assert( std::is_same<O::value_type, T>(), "" );
113     static_assert( std::is_default_constructible<O>(), "" );
114     { O o; }
115     static_assert( !std::is_copy_constructible<O>(), "" );
116     static_assert( !std::is_copy_assignable<O>(), "" );
117     static_assert( std::is_move_constructible<O>(), "" );
118     { O o; auto moved_to = std::move(o); }
119     static_assert( std::is_move_assignable<O>(), "" );
120     { O o, p; p = std::move(o); }
121   }
122 
123   {
124     using T = no_copy_assignment;
125     using O = std::experimental::optional<T>;
126     static_assert( std::is_default_constructible<O>(), "" );
127     { O o; }
128     static_assert( std::is_copy_constructible<O>(), "" );
129     { O o; auto copy = o; }
130     static_assert( !std::is_copy_assignable<O>(), "" );
131     static_assert( std::is_move_constructible<O>(), "" );
132     { O o; auto moved_to = std::move(o); }
133     static_assert( std::is_move_assignable<O>(), "" );
134     { O o, p; p = std::move(o); }
135   }
136 
137   {
138     using T = no_copy;
139     using O = std::experimental::optional<T>;
140     static_assert( std::is_same<O::value_type, T>(), "" );
141     static_assert( std::is_default_constructible<O>(), "" );
142     { O o; }
143     static_assert( !std::is_copy_constructible<O>(), "" );
144     static_assert( !std::is_copy_assignable<O>(), "" );
145     static_assert( std::is_move_constructible<O>(), "" );
146     { O o; auto moved_to = std::move(o); }
147     static_assert( std::is_move_assignable<O>(), "" );
148     { O o, p; p = std::move(o); }
149   }
150 
151   {
152     using T = no_move_constructor;
153     using O = std::experimental::optional<T>;
154     static_assert( std::is_same<O::value_type, T>(), "" );
155     static_assert( std::is_default_constructible<O>(), "" );
156     { O o; }
157     static_assert( std::is_copy_constructible<O>(), "" );
158     { O o; auto copy = o; }
159     static_assert( std::is_copy_assignable<O>(), "" );
160     /*
161      * T should be move constructible due to [12.8/11], which is a new rule in C++1y
162      * not yet implemented by GCC. Because there is already a special exception in C++11
163      * for the generation of the special members that GCC implements (at least some of the
164      * time), this does not affect the std::experimental::optional implementation however. So the assertion
165      * for T should be changed (or removed altogether) when the time comes, but the rest
166      * should however remain correct and unchanged.
167      */
168     static_assert( !std::is_move_constructible<T>(), "" );
169     static_assert( std::is_move_constructible<O>(), "" );
170     { O o; auto moved_to = std::move(o); }
171     static_assert( std::is_move_assignable<O>(), "" );
172     { O o, p; p = std::move(o); }
173   }
174 
175   {
176     using T = no_move_assignment;
177     using O = std::experimental::optional<T>;
178     static_assert( std::is_same<O::value_type, T>(), "" );
179     static_assert( std::is_default_constructible<O>(), "" );
180     { O o; }
181     static_assert( std::is_copy_constructible<O>(), "" );
182     { O o; auto copy = o; }
183     static_assert( std::is_copy_assignable<O>(), "" );
184     { O o, p; p = o; }
185     static_assert( std::is_move_constructible<O>(), "" );
186     { O o; auto moved_to = std::move(o); }
187     /*
188      * Paragraph 23 of same leads to a similar situation but with respect to move
189      * assignment.
190      */
191     static_assert( !std::is_move_assignable<T>(), "" );
192     static_assert( std::is_move_assignable<O>(), "" );
193     { O o, p; p = std::move(o); }
194   }
195 
196   {
197     using T = no_move;
198     using O = std::experimental::optional<T>;
199     static_assert( std::is_same<O::value_type, T>(), "" );
200     static_assert( std::is_default_constructible<O>(), "" );
201     { O o; }
202     static_assert( std::is_copy_constructible<O>(), "" );
203     { O o; auto copy = o; }
204     static_assert( std::is_copy_assignable<O>(), "" );
205     { O o, p; p = o; }
206     static_assert( std::is_move_constructible<O>(), "" );
207     { O o; auto moved_to = std::move(o); }
208     static_assert( std::is_move_assignable<O>(), "" );
209     { O o, p; p = std::move(o); }
210   }
211 
212   {
213     using T = only_destructible;
214     using O = std::experimental::optional<T>;
215     static_assert( std::is_same<O::value_type, T>(), "" );
216     static_assert( std::is_default_constructible<O>(), "" );
217     { O o; }
218     static_assert( !std::is_copy_constructible<O>(), "" );
219     static_assert( !std::is_copy_assignable<O>(), "" );
220     static_assert( !std::is_move_constructible<O>(), "" );
221     static_assert( !std::is_move_assignable<O>(), "" );
222   }
223 
224   {
225     /*
226      * Should not complain about 'invalid' specializations as long as
227      * they're not instantiated.
228      */
229     using A = std::experimental::optional<int&>;
230     using B = std::experimental::optional<int&&>;
231     using C1 = std::experimental::optional<std::experimental::in_place_t>;
232     using C2 = std::experimental::optional<std::experimental::in_place_t const>;
233     using C3 = std::experimental::optional<std::experimental::in_place_t volatile>;
234     using C4 = std::experimental::optional<std::experimental::in_place_t const volatile>;
235     using D1 = std::experimental::optional<std::experimental::nullopt_t>;
236     using D2 = std::experimental::optional<std::experimental::nullopt_t const>;
237     using D3 = std::experimental::optional<std::experimental::nullopt_t volatile>;
238     using D4 = std::experimental::optional<std::experimental::nullopt_t const volatile>;
239 
240     using X = std::tuple<A, B, C1, C2, C3, C4, D1, D2, D3, D4>;
241   }
242 
243   {
244     std::experimental::optional<const int> o { 42 };
245     static_assert( std::is_same<decltype(o)::value_type, const int>(), "" );
246     VERIFY( o );
247     VERIFY( *o == 42 );
248   }
249 
250   {
251     constexpr std::experimental::optional<const int> o { 33 };
252     static_assert( std::is_same<decltype(o)::value_type, const int>(), "" );
253     static_assert( o, "" );
254     static_assert( *o == 33, "" );
255   }
256 }
257