131
131
#include < iterator>
132
132
#include < ranges>
133
133
#include < algorithm>
134
- // libstdc++ sometime after GCC 10 got a dependency on linking TBB if <execution> is
135
- // included, so let's not pull in that header in our "import std;" simulation mode
136
- #if not defined(__GLIBCXX__) || __GLIBCXX__ < 20210101
137
- #include < execution>
138
- #endif
139
134
#include < bit>
140
135
#include < cfenv>
141
136
#include < cmath>
185
180
#endif
186
181
#include < thread>
187
182
#include < iso646.h>
183
+
184
+ // libstdc++ currently has a dependency on linking TBB if <execution> is
185
+ // included, and TBB seems to be not automatically installed and linkable
186
+ // on some GCC installations, so let's not pull in that little-used header
187
+ // in our -pure-cpp2 "import std;" simulation mode... if you need this,
188
+ // use mixed mode (not -pure-cpp2) and #include all the headers you need
189
+ // including this one
190
+ //
191
+ // #include <execution>
188
192
#endif
189
193
190
194
// Otherwise, we're not in -pure-cpp2 and so just #include
@@ -395,9 +399,11 @@ class deferred_init {
395
399
template <typename U>
396
400
friend class out ;
397
401
402
+ auto destroy () -> void { if (init) { t ().~T (); } init = false ; }
403
+
398
404
public:
399
405
deferred_init () noexcept { }
400
- ~deferred_init () noexcept { if (init) t (). ~T (); }
406
+ ~deferred_init () noexcept { destroy (); }
401
407
auto value () noexcept -> T& { Default.expects (init); return t (); }
402
408
403
409
auto construct (auto && ...args) -> void { Default.expects (!init); new (&data) T (std::forward<decltype (args)>(args)...); init = true ; }
@@ -411,46 +417,79 @@ class out {
411
417
T* t;
412
418
deferred_init<T>* dt;
413
419
};
414
- int uncaught_count = std::uncaught_exceptions() ;
420
+ out<T>* ot = nullptr ;
415
421
bool has_t ;
416
- bool called_construct = false ;
422
+
423
+ // Each out in a chain contains its own uncaught_count ...
424
+ int uncaught_count = std::uncaught_exceptions();
425
+ // ... but all in a chain share the topmost called_construct_
426
+ bool called_construct_ = false ;
417
427
418
428
public:
419
- out (T* t) noexcept : t{t}, has_t {true } { }
420
- out (deferred_init<T>* dt) noexcept : dt{dt}, has_t {false } { }
429
+ out (T* t) noexcept : t{ t}, has_t {true } { Default.expects ( t); }
430
+ out (deferred_init<T>* dt) noexcept : dt{dt}, has_t {false } { Default.expects (dt); }
431
+ out (out<T>* ot) noexcept : ot{ot}, has_t {ot->has_t } { Default.expects (ot);
432
+ if (has_t ) { t = ot->t ; }
433
+ else { dt = ot->dt ; }
434
+ }
435
+
436
+ auto called_construct () -> bool& {
437
+ if (ot) { return ot->called_construct (); }
438
+ else { return called_construct_; }
439
+ }
421
440
422
441
// In the case of an exception, if the parameter was uninitialized
423
442
// then leave it in the same state on exit (strong guarantee)
424
443
~out () {
425
- if (called_construct && uncaught_count != std::uncaught_exceptions ()) {
444
+ if (called_construct () && uncaught_count != std::uncaught_exceptions ()) {
426
445
Default.expects (!has_t );
427
- dt->value ().~T ();
446
+ dt->destroy ();
447
+ called_construct () = false ;
428
448
}
429
449
}
430
450
431
- auto construct (auto ...args) -> void {
451
+ auto construct (auto && ...args) -> void {
432
452
if (has_t ) {
433
- *t = T (args...);
434
- }
435
- else if (dt->init ) {
436
- dt->value () = T (args...);
453
+ Default.expects ( t );
454
+ *t = T (std::forward<decltype (args)>(args)...);
437
455
}
438
456
else {
439
- dt->construct (args...);
440
- called_construct = true ;
457
+ Default.expects ( dt );
458
+ if (dt->init ) {
459
+ dt->value () = T (std::forward<decltype (args)>(args)...);
460
+ }
461
+ else {
462
+ dt->construct (std::forward<decltype (args)>(args)...);
463
+ called_construct () = true ;
464
+ }
441
465
}
442
466
}
443
467
444
- auto construct_list (auto ...args) -> void {
468
+ auto construct_list (auto && ...args) -> void {
445
469
if (has_t ) {
446
- *t = T{args...};
470
+ Default.expects ( t );
471
+ *t = T{std::forward<decltype (args)>(args)...};
472
+ }
473
+ else {
474
+ Default.expects ( dt );
475
+ if (dt->init ) {
476
+ dt->value () = T{std::forward<decltype (args)>(args)...};
477
+ }
478
+ else {
479
+ dt->construct_list (std::forward<decltype (args)>(args)...);
480
+ called_construct () = true ;
481
+ }
447
482
}
448
- else if (dt->init ) {
449
- dt->value () = T{args...};
483
+ }
484
+
485
+ auto value () noexcept -> T& {
486
+ if (has_t ) {
487
+ Default.expects ( t );
488
+ return *t;
450
489
}
451
490
else {
452
- dt-> construct_list (args... );
453
- called_construct = true ;
491
+ Default. expects ( dt );
492
+ return dt-> value () ;
454
493
}
455
494
}
456
495
};
@@ -860,8 +899,8 @@ class c_raii {
860
899
861
900
c_raii (c_raii const &) = delete ;
862
901
auto operator =(c_raii const &) = delete ;
863
- c_raii (c_raii&& that) : t {std::move (that.t )}, dtor {that.dtor } { that.dtor = nullptr ; }
864
- auto operator =(c_raii&& that) { t = std::move (that.t ); dtor = that.dtor ; that.dtor = nullptr ; }
902
+ c_raii (c_raii&& that) noexcept : t {std::move (that.t )}, dtor {that.dtor } { that.dtor = nullptr ; }
903
+ auto operator =(c_raii&& that) noexcept { t = std::move (that.t ); dtor = that.dtor ; that.dtor = nullptr ; }
865
904
};
866
905
867
906
inline auto fopen ( const char * filename, const char * mode ) {
0 commit comments