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