Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/experimental/scope
1 // <experimental/scope> -*- C++ -*- 2 3 // Copyright The GNU Toolchain Authors. 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 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file experimental/scope 26 * This is a TS C++ Library header. 27 * @ingroup libfund-ts 28 */ 29 30 #ifndef _GLIBCXX_EXPERIMENTAL_SCOPE 31 #define _GLIBCXX_EXPERIMENTAL_SCOPE 1 32 33 #ifdef _GLIBCXX_SYSHDR 34 #pragma GCC system_header 35 #endif 36 37 #include <bits/requires_hosted.h> // experimental is currently omitted 38 39 #if __cplusplus >= 202002L 40 41 #include <concepts> 42 #include <exception> // uncaught_exceptions 43 #include <bits/refwrap.h> 44 45 namespace std _GLIBCXX_VISIBILITY(default) 46 { 47 _GLIBCXX_BEGIN_NAMESPACE_VERSION 48 namespace experimental::inline fundamentals_v3 49 { 50 #define __cpp_lib_experimental_scope 201902 51 52 template<typename _Tp, typename _Up> 53 concept __not_same_as = !same_as<_Tp, _Up>; 54 55 template<typename _Tp> 56 concept __not_lvalue_ref = !is_lvalue_reference_v<_Tp>; 57 58 template<typename _Ef> 59 class [[nodiscard]] scope_exit 60 { 61 public: 62 template<typename _Efp> 63 requires __not_same_as<remove_cvref_t<_Efp>, scope_exit> 64 && constructible_from<_Ef, _Efp> 65 [[nodiscard]] explicit 66 scope_exit(_Efp&& __f) noexcept(is_nothrow_constructible_v<_Ef, _Efp&>) 67 #ifdef __cpp_exceptions 68 try 69 #endif 70 : _M_exit_function(__f) 71 { } 72 #ifdef __cpp_exceptions 73 catch (...) { __f(); } 74 #endif 75 76 template<typename _Efp> 77 requires __not_same_as<remove_cvref_t<_Efp>, scope_exit> 78 && constructible_from<_Ef, _Efp> 79 && __not_lvalue_ref<_Efp> 80 && is_nothrow_constructible_v<_Ef, _Efp> 81 explicit 82 scope_exit(_Efp&& __f) noexcept 83 : _M_exit_function(std::forward<_Efp>(__f)) 84 { } 85 86 scope_exit(scope_exit&& __rhs) noexcept 87 requires is_nothrow_move_constructible_v<_Ef> 88 : _M_exit_function(std::forward<_Ef>(__rhs._M_exit_function)) 89 { __rhs.release(); } 90 91 scope_exit(scope_exit&& __rhs) 92 noexcept(is_nothrow_copy_constructible_v<_Ef>) 93 requires (!is_nothrow_move_constructible_v<_Ef>) 94 && is_copy_constructible_v<_Ef> 95 : _M_exit_function(__rhs._M_exit_function) 96 { __rhs.release(); } 97 98 scope_exit(const scope_exit&) = delete; 99 scope_exit& operator=(const scope_exit&) = delete; 100 scope_exit& operator=(scope_exit&&) = delete; 101 102 ~scope_exit() noexcept 103 { 104 if (_M_execute_on_destruction) 105 _M_exit_function(); 106 } 107 108 void release() noexcept { _M_execute_on_destruction = false; } 109 110 private: 111 [[no_unique_address]] _Ef _M_exit_function; 112 bool _M_execute_on_destruction = true; 113 }; 114 115 template<typename _Ef> 116 scope_exit(_Ef) -> scope_exit<_Ef>; 117 118 template<typename _Ef> 119 class [[nodiscard]] scope_fail 120 { 121 public: 122 template<typename _Efp> 123 requires __not_same_as<remove_cvref_t<_Efp>, scope_fail> 124 && constructible_from<_Ef, _Efp> 125 explicit 126 scope_fail(_Efp&& __f) noexcept(is_nothrow_constructible_v<_Ef, _Efp&>) 127 #ifdef __cpp_exceptions 128 try 129 #endif 130 : _M_exit_function(__f) 131 { } 132 #ifdef __cpp_exceptions 133 catch (...) { __f(); } 134 #endif 135 136 template<typename _Efp> 137 requires __not_same_as<remove_cvref_t<_Efp>, scope_fail> 138 && constructible_from<_Ef, _Efp> 139 && __not_lvalue_ref<_Efp> 140 && is_nothrow_constructible_v<_Ef, _Efp> 141 explicit 142 scope_fail(_Efp&& __f) noexcept 143 : _M_exit_function(std::forward<_Efp>(__f)) 144 { } 145 146 scope_fail(scope_fail&& __rhs) noexcept 147 requires is_nothrow_move_constructible_v<_Ef> 148 : _M_exit_function(std::forward<_Ef>(__rhs._M_exit_function)) 149 { __rhs.release(); } 150 151 scope_fail(scope_fail&& __rhs) 152 noexcept(is_nothrow_copy_constructible_v<_Ef>) 153 requires (!is_nothrow_move_constructible_v<_Ef>) 154 && is_copy_constructible_v<_Ef> 155 : _M_exit_function(__rhs._M_exit_function) 156 { __rhs.release(); } 157 158 scope_fail(const scope_fail&) = delete; 159 scope_fail& operator=(const scope_fail&) = delete; 160 scope_fail& operator=(scope_fail&&) = delete; 161 162 ~scope_fail() noexcept 163 { 164 if (std::uncaught_exceptions() > _M_uncaught_init) 165 _M_exit_function(); 166 } 167 168 void release() noexcept { _M_uncaught_init = __INT_MAX__; } 169 170 private: 171 [[no_unique_address]] _Ef _M_exit_function; 172 int _M_uncaught_init = std::uncaught_exceptions(); 173 }; 174 175 template<typename _Ef> 176 scope_fail(_Ef) -> scope_fail<_Ef>; 177 178 template<typename _Ef> 179 class [[nodiscard]] scope_success 180 { 181 public: 182 template<typename _Efp> 183 requires __not_same_as<remove_cvref_t<_Efp>, scope_success> 184 && constructible_from<_Ef, _Efp> 185 explicit 186 scope_success(_Efp&& __f) noexcept(is_nothrow_constructible_v<_Ef, _Efp&>) 187 : _M_exit_function(__f) 188 { } 189 190 template<typename _Efp> 191 requires __not_same_as<remove_cvref_t<_Efp>, scope_success> 192 && constructible_from<_Ef, _Efp> 193 && __not_lvalue_ref<_Efp> 194 && is_nothrow_constructible_v<_Ef, _Efp> 195 explicit 196 scope_success(_Efp&& __f) noexcept 197 : _M_exit_function(std::forward<_Efp>(__f)) 198 { } 199 200 scope_success(scope_success&& __rhs) noexcept 201 requires is_nothrow_move_constructible_v<_Ef> 202 : _M_exit_function(std::forward<_Ef>(__rhs._M_exit_function)) 203 { __rhs.release(); } 204 205 scope_success(scope_success&& __rhs) 206 noexcept(is_nothrow_copy_constructible_v<_Ef>) 207 requires (!is_nothrow_move_constructible_v<_Ef>) 208 && is_copy_constructible_v<_Ef> 209 : _M_exit_function(__rhs._M_exit_function) 210 { __rhs.release(); } 211 212 scope_success(const scope_success&) = delete; 213 scope_success& operator=(const scope_success&) = delete; 214 scope_success& operator=(scope_success&&) = delete; 215 216 ~scope_success() noexcept(noexcept(this->_M_exit_function())) 217 { 218 if (std::uncaught_exceptions() <= _M_uncaught_init) 219 _M_exit_function(); 220 } 221 222 void release() noexcept { _M_uncaught_init = -__INT_MAX__; } 223 224 private: 225 [[no_unique_address]] _Ef _M_exit_function; 226 int _M_uncaught_init = std::uncaught_exceptions(); 227 }; 228 229 template<typename _Ef> 230 scope_success(_Ef) -> scope_success<_Ef>; 231 232 template<typename _Resrc, typename _Del> 233 class [[nodiscard]] unique_resource 234 { 235 static_assert(!is_rvalue_reference_v<_Resrc>); 236 static_assert(!is_reference_v<_Del>); 237 238 struct _Dummy { constexpr void release() { } }; 239 240 template<typename _Tp> 241 struct _Wrap 242 { 243 template<typename _Up> 244 requires is_constructible_v<_Tp, _Up> 245 _Wrap(_Up&&) 246 noexcept(is_nothrow_constructible_v<_Tp, _Up>); 247 248 template<typename _Up, typename _Del2> 249 requires is_constructible_v<_Tp, _Up> 250 _Wrap(_Up&& __r, _Del2&& __d) 251 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 252 : _M_t(std::forward<_Up>(__r)) 253 { __d.release(); } 254 255 _Wrap() = default; 256 257 _Wrap(_Wrap&&) = default; 258 259 _Wrap(_Wrap&& __rhs) noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) 260 requires (!is_nothrow_move_constructible_v<_Tp>) 261 : _M_t(__rhs._M_t) 262 { } 263 264 _Wrap& operator=(const _Wrap&) = default; 265 266 _Wrap& operator=(_Wrap&&) = default; 267 268 constexpr _Tp& get() noexcept { return _M_t; } 269 constexpr const _Tp& get() const noexcept { return _M_t; } 270 271 [[no_unique_address]] _Tp _M_t{}; 272 }; 273 274 template<typename _Tp> 275 struct _Wrap<_Tp&> 276 { 277 template<typename _Up> 278 requires is_constructible_v<reference_wrapper<_Tp>, _Up> 279 _Wrap(_Up&&) 280 noexcept(is_nothrow_constructible_v<reference_wrapper<_Tp>, _Up>); 281 282 template<typename _Up, typename _Del2> 283 _Wrap(_Up&& __r, _Del2&& __d) 284 noexcept(is_nothrow_constructible_v<reference_wrapper<_Tp>, _Up>) 285 : _M_p(__builtin_addressof(static_cast<_Tp&>(__r))) 286 { __d.release(); } 287 288 _Wrap() = delete; 289 290 _Wrap(const _Wrap&) = default; 291 292 _Wrap& operator=(const _Wrap&) = default; 293 294 _Tp& get() noexcept { return *_M_p; } 295 const _Tp& get() const noexcept { return *_M_p; } 296 297 _Tp* _M_p = nullptr; 298 }; 299 300 using _Res1 = _Wrap<_Resrc>; 301 302 template<typename _Tp, typename _Up> 303 requires is_constructible_v<_Tp, _Up> 304 && (is_nothrow_constructible_v<_Tp, _Up> 305 || is_constructible_v<_Tp, _Up&>) 306 using _Fwd_t 307 = __conditional_t<is_nothrow_constructible_v<_Tp, _Up>, _Up, _Up&>; 308 309 template<typename _Tp, typename _Up> 310 static constexpr _Fwd_t<_Tp, _Up> 311 _S_fwd(_Up& __u) 312 { return static_cast<_Fwd_t<_Tp, _Up>&&>(__u); } 313 314 template<typename _Tp, typename _Up, typename _Del2, typename _Res2> 315 static constexpr auto 316 _S_guard(_Del2& __d, _Res2& __r) 317 { 318 if constexpr (is_nothrow_constructible_v<_Tp, _Up>) 319 return _Dummy{}; 320 else 321 return scope_fail{[&] { __d(__r); }}; 322 } 323 324 public: 325 unique_resource() = default; 326 327 template<typename _Res2, typename _Del2> 328 requires requires { 329 typename _Fwd_t<_Res1, _Res2>; 330 typename _Fwd_t<_Del, _Del2>; 331 } 332 unique_resource(_Res2&& __r, _Del2&& __d) 333 noexcept((is_nothrow_constructible_v<_Res1, _Res2> 334 || is_nothrow_constructible_v<_Res1, _Res2&>) 335 && 336 (is_nothrow_constructible_v<_Del, _Del2> 337 || is_nothrow_constructible_v<_Del, _Del2&>)) 338 : _M_res(_S_fwd<_Res1, _Res2>(__r), 339 _S_guard<_Res1, _Res2>(__d, __r)), 340 _M_del(_S_fwd<_Del, _Del2>(__d), 341 _S_guard<_Del, _Del2>(__d, _M_res.get())), 342 _M_exec_on_reset(true) 343 { } 344 345 unique_resource(unique_resource&& __rhs) noexcept 346 requires is_nothrow_move_constructible_v<_Res1> 347 && is_nothrow_move_constructible_v<_Del> 348 : _M_res(std::move(__rhs._M_res)), 349 _M_del(std::move(__rhs._M_del)), 350 _M_exec_on_reset(std::__exchange(__rhs._M_exec_on_reset, false)) 351 { } 352 353 unique_resource(unique_resource&& __rhs) 354 requires is_nothrow_move_constructible_v<_Res1> 355 && (!is_nothrow_move_constructible_v<_Del>) 356 : _M_res(std::move(__rhs._M_res)), 357 _M_del(_S_fwd<_Del, _Del>(__rhs._M_del.get()), 358 scope_fail([&]{ 359 if (__rhs._M_exec_on_reset) 360 { 361 __rhs._M_del.get()(_M_res.get()); 362 __rhs.release(); 363 } 364 })), 365 _M_exec_on_reset(std::__exchange(__rhs._M_exec_on_reset, false)) 366 { } 367 368 unique_resource(unique_resource&& __rhs) 369 requires (!is_nothrow_move_constructible_v<_Res1>) 370 : unique_resource(__rhs._M_res.get(), __rhs._M_del.get(), _Dummy{}) 371 { 372 if (__rhs._M_exec_on_reset) 373 { 374 _M_exec_on_reset = true; 375 __rhs._M_exec_on_reset = false; 376 } 377 } 378 379 // 3.3.3.3, Destructor 380 ~unique_resource() { reset(); } 381 382 // 3.3.3.4, Assignment 383 unique_resource& 384 operator=(unique_resource&& __rhs) 385 noexcept(is_nothrow_move_assignable_v<_Res1> 386 && is_nothrow_move_assignable_v<_Del>) 387 { 388 reset(); 389 if constexpr (is_nothrow_move_assignable_v<_Res1>) 390 { 391 if constexpr (is_nothrow_move_assignable_v<_Del>) 392 { 393 _M_res = std::move(__rhs._M_res); 394 _M_del = std::move(__rhs._M_del); 395 } 396 else 397 { 398 _M_del = __rhs._M_del; 399 _M_res = std::move(__rhs._M_res); 400 } 401 } 402 else 403 { 404 if constexpr (is_nothrow_move_assignable_v<_Del>) 405 { 406 _M_res = __rhs._M_res; 407 _M_del = std::move(__rhs._M_del); 408 } 409 else 410 { 411 _M_res = __rhs._M_res; 412 _M_del = __rhs._M_del; 413 } 414 } 415 _M_exec_on_reset = std::__exchange(__rhs._M_exec_on_reset, false); 416 return *this; 417 } 418 419 // 3.3.3.5, Other member functions 420 void 421 reset() noexcept 422 { 423 if (_M_exec_on_reset) 424 { 425 _M_exec_on_reset = false; 426 _M_del.get()(_M_res.get()); 427 } 428 } 429 430 template<typename _Res2> 431 void 432 reset(_Res2&& __r) 433 { 434 reset(); 435 if constexpr (is_nothrow_assignable_v<_Res1&, _Res2>) 436 _M_res.get() = std::forward<_Res2>(__r); 437 else 438 _M_res.get() = const_cast<const remove_reference_t<_Res2>&>(__r); 439 _M_exec_on_reset = true; 440 } 441 442 void 443 release() noexcept 444 { _M_exec_on_reset = false; } 445 446 const _Resrc& 447 get() const noexcept 448 { return _M_res.get(); } 449 450 add_lvalue_reference_t<remove_pointer_t<_Resrc>> 451 operator*() const noexcept 452 requires is_pointer_v<_Resrc> && (!is_void_v<remove_pointer_t<_Resrc>>) 453 { return *get(); } 454 455 _Resrc operator->() const noexcept 456 requires is_pointer_v<_Resrc> 457 { return _M_res.get(); } 458 459 const _Del& 460 get_deleter() const noexcept 461 { return _M_del.get(); } 462 463 private: 464 [[no_unique_address]] _Res1 _M_res{}; 465 [[no_unique_address]] _Wrap<_Del> _M_del{}; 466 bool _M_exec_on_reset = false; 467 468 template<typename _Res2, typename _Del2, typename _St> 469 friend unique_resource<decay_t<_Res2>, decay_t<_Del2>> 470 make_unique_resource_checked(_Res2&&, const _St&, _Del2&&) 471 noexcept(is_nothrow_constructible_v<decay_t<_Res2>, _Res2> 472 && is_nothrow_constructible_v<decay_t<_Del2>, _Del2>); 473 474 template<typename _Res2, typename _Del2> 475 unique_resource(_Res2&& __r, _Del2&& __d, _Dummy __noop) 476 noexcept(is_nothrow_constructible_v<_Resrc, _Res2> 477 && is_nothrow_constructible_v<_Del, _Del2>) 478 : _M_res(std::forward<_Res2>(__r), __noop), 479 _M_del(std::forward<_Del>(__d), __noop) 480 { } 481 }; 482 483 template<typename _Resrc, typename _Del> 484 unique_resource(_Resrc, _Del) -> unique_resource<_Resrc, _Del>; 485 486 template<typename _Resrc, typename _Del, typename _St = decay_t<_Resrc>> 487 unique_resource<decay_t<_Resrc>, decay_t<_Del>> 488 make_unique_resource_checked(_Resrc&& __r, const _St& __invalid, _Del&& __d) 489 noexcept(is_nothrow_constructible_v<decay_t<_Resrc>, _Resrc> 490 && is_nothrow_constructible_v<decay_t<_Del>, _Del>) 491 { 492 if (__r == __invalid) 493 return { std::forward<_Resrc>(__r), std::forward<_Del>(__d), {} }; 494 return { std::forward<_Resrc>(__r), std::forward<_Del>(__d) }; 495 } 496 497 } // namespace experimental::fundamentals_v3 498 _GLIBCXX_END_NAMESPACE_VERSION 499 } // namespace std 500 #endif // C++20 501 #endif // _GLIBCXX_EXPERIMENTAL_SCOPE