201201 #include < type_traits>
202202 #include < new>
203203 #include < memory>
204+ #include < tuple>
204205 #include < string>
205206 #include < string_view>
206207 #include < vector>
216217 #include < compare>
217218 #include < iterator>
218219 #include < concepts>
220+ #include < system_error>
219221
220222 #ifndef CPP2_NO_EXCEPTIONS
221223 #include < exception>
@@ -324,8 +326,8 @@ class contract_group {
324326 using handler = void (*)(CPP2_MESSAGE_PARAM msg CPP2_SOURCE_LOCATION_PARAM);
325327
326328 constexpr contract_group (handler h = {}) : reporter(h) { }
327- constexpr auto set_handler (handler h) -> handler ;
328- constexpr auto get_handler () const -> handler { return reporter; }
329+ constexpr auto set_handler (handler h);
330+ constexpr auto get_handler () const -> handler { return reporter; }
329331 constexpr auto expects (bool b, CPP2_MESSAGE_PARAM msg = " " CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT)
330332 -> void { if (!b) reporter (msg CPP2_SOURCE_LOCATION_ARG); }
331333private:
@@ -373,11 +375,9 @@ auto inline Testing = contract_group(
373375 }
374376);
375377
376- constexpr auto contract_group::set_handler (handler h) -> handler {
378+ constexpr auto contract_group::set_handler (handler h) {
377379 Default.expects (h);
378- auto old = reporter;
379380 reporter = h;
380- return old;
381381}
382382
383383
@@ -681,19 +681,37 @@ class out {
681681//
682682// -----------------------------------------------------------------------
683683//
684- #ifdef _MSC_VER
684+ #if defined( _MSC_VER) && !defined(__clang_major__)
685685 #define CPP2_FORCE_INLINE __forceinline
686686 #define CPP2_FORCE_INLINE_LAMBDA [[msvc::forceinline]]
687+ #define CPP2_LAMBDA_NO_DISCARD
687688#else
688689 #define CPP2_FORCE_INLINE __attribute__ ((always_inline))
689690 #define CPP2_FORCE_INLINE_LAMBDA __attribute__ ((always_inline))
691+
692+ #if defined (__clang_major__)
693+ // Also check __cplusplus, only to satisfy Clang -pedantic-errors
694+ #if __cplusplus >= 202302L && (__clang_major__ > 13 || (__clang_major__ == 13 && __clang_minor__ >= 2 ))
695+ #define CPP2_LAMBDA_NO_DISCARD [[nodiscard]]
696+ #else
697+ #define CPP2_LAMBDA_NO_DISCARD
698+ #endif
699+ #elif defined(__GNUC__)
700+ #if __GNUC__ >= 9
701+ #define CPP2_LAMBDA_NO_DISCARD [[nodiscard]]
702+ #else
703+ #define CPP2_LAMBDA_NO_DISCARD
704+ #endif
705+ #else
706+ #define CPP2_LAMBDA_NO_DISCARD
707+ #endif
690708#endif
691709
692710
693711// Note: [&] is because a nested UFCS might be viewed as trying to capture 'this'
694712
695713#define CPP2_UFCS (FUNCNAME,PARAM1,...) \
696- [&](auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
714+ [&] CPP2_LAMBDA_NO_DISCARD (auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
697715 if constexpr (requires { CPP2_FORWARD (obj).FUNCNAME (CPP2_FORWARD (params)...); }) { \
698716 return CPP2_FORWARD (obj).FUNCNAME (CPP2_FORWARD (params)...); \
699717 } else { \
@@ -702,7 +720,7 @@ class out {
702720}(PARAM1, __VA_ARGS__)
703721
704722#define CPP2_UFCS_0 (FUNCNAME,PARAM1 ) \
705- [&](auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
723+ [&] CPP2_LAMBDA_NO_DISCARD (auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
706724 if constexpr (requires { CPP2_FORWARD (obj).FUNCNAME (); }) { \
707725 return CPP2_FORWARD (obj).FUNCNAME (); \
708726 } else { \
@@ -713,7 +731,7 @@ class out {
713731#define CPP2_UFCS_REMPARENS (...) __VA_ARGS__
714732
715733#define CPP2_UFCS_TEMPLATE (FUNCNAME,TEMPARGS,PARAM1,...) \
716- [&](auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
734+ [&] CPP2_LAMBDA_NO_DISCARD (auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
717735 if constexpr (requires { CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD (params)...); }) { \
718736 return CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD (params)...); \
719737 } else { \
@@ -722,7 +740,7 @@ class out {
722740}(PARAM1, __VA_ARGS__)
723741
724742#define CPP2_UFCS_TEMPLATE_0 (FUNCNAME,TEMPARGS,PARAM1 ) \
725- [&](auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
743+ [&] CPP2_LAMBDA_NO_DISCARD (auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
726744 if constexpr (requires { CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); }) { \
727745 return CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); \
728746 } else { \
@@ -734,7 +752,7 @@ class out {
734752// But for non-local lambdas [&] is not allowed
735753
736754#define CPP2_UFCS_NONLOCAL (FUNCNAME,PARAM1,...) \
737- [](auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
755+ [] CPP2_LAMBDA_NO_DISCARD (auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
738756 if constexpr (requires { CPP2_FORWARD (obj).FUNCNAME (CPP2_FORWARD (params)...); }) { \
739757 return CPP2_FORWARD (obj).FUNCNAME (CPP2_FORWARD (params)...); \
740758 } else { \
@@ -743,7 +761,7 @@ class out {
743761}(PARAM1, __VA_ARGS__)
744762
745763#define CPP2_UFCS_0_NONLOCAL (FUNCNAME,PARAM1 ) \
746- [](auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
764+ [] CPP2_LAMBDA_NO_DISCARD (auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
747765 if constexpr (requires { CPP2_FORWARD (obj).FUNCNAME (); }) { \
748766 return CPP2_FORWARD (obj).FUNCNAME (); \
749767 } else { \
@@ -752,7 +770,7 @@ class out {
752770}(PARAM1)
753771
754772#define CPP2_UFCS_TEMPLATE_NONLOCAL (FUNCNAME,TEMPARGS,PARAM1,...) \
755- [](auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
773+ [] CPP2_LAMBDA_NO_DISCARD (auto && obj, auto && ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
756774 if constexpr (requires { CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD (params)...); }) { \
757775 return CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD (params)...); \
758776 } else { \
@@ -761,7 +779,7 @@ class out {
761779}(PARAM1, __VA_ARGS__)
762780
763781#define CPP2_UFCS_TEMPLATE_0_NONLOCAL (FUNCNAME,TEMPARGS,PARAM1 ) \
764- [](auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
782+ [] CPP2_LAMBDA_NO_DISCARD (auto && obj) CPP2_FORCE_INLINE_LAMBDA -> decltype (auto ) { \
765783 if constexpr (requires { CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); }) { \
766784 return CPP2_FORWARD (obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); \
767785 } else { \
@@ -1334,82 +1352,67 @@ constexpr auto as( X const& x ) -> decltype(auto)
13341352
13351353// -----------------------------------------------------------------------
13361354//
1337- // A variation of GSL's final_action_success and finally to run only on success
1338- // (based on a PR I contributed to Microsoft GSL)
1355+ // A variation of GSL's final_action_success / finally
13391356//
1340- // final_action_success ensures something is run at the end of a scope
1341- // if no exception is thrown
1357+ // finally ensures something is run at the end of a scope always
13421358//
1343- // finally_success is a convenience function to make a final_action_success_success
1359+ // finally_success ensures something is run at the end of a scope
1360+ // if no exception is thrown
13441361//
13451362// -----------------------------------------------------------------------
13461363//
13471364
13481365template <class F >
1349- class final_action_success
1366+ class finally_success
13501367{
13511368public:
1352- explicit final_action_success (const F& ff) noexcept : f{ff} { }
1353- explicit final_action_success (F&& ff) noexcept : f{std::move (ff)} { }
1369+ explicit finally_success (const F& ff) noexcept : f{ff} { }
1370+ explicit finally_success (F&& ff) noexcept : f{std::move (ff)} { }
13541371
1355- ~final_action_success () noexcept
1372+ ~finally_success () noexcept
13561373 {
13571374 if (invoke && ecount == std::uncaught_exceptions ()) {
13581375 f ();
13591376 }
13601377 }
13611378
1362- final_action_success (final_action_success && that) noexcept
1379+ finally_success (finally_success && that) noexcept
13631380 : f(std::move(that.f)), invoke(std::exchange(that.invoke, false ))
13641381 { }
13651382
1366- final_action_success (final_action_success const &) = delete ;
1367- void operator = (final_action_success const &) = delete ;
1368- void operator = (final_action_success &&) = delete ;
1383+ finally_success (finally_success const &) = delete ;
1384+ void operator = (finally_success const &) = delete ;
1385+ void operator = (finally_success &&) = delete ;
13691386
13701387private:
13711388 F f;
13721389 int ecount = std::uncaught_exceptions();
13731390 bool invoke = true ;
13741391};
13751392
1376- [[nodiscard]] auto finally_success (auto && f) noexcept
1377- {
1378- return final_action_success<CPP2_TYPEOF (f)>{CPP2_FORWARD (f)};
1379- }
1380-
1381-
1382- //
1383- // Same, but clean up also on exceptional paths
1384- //
13851393
13861394template <class F >
1387- class final_action
1395+ class finally
13881396{
13891397public:
1390- explicit final_action (const F& ff) noexcept : f{ff} { }
1391- explicit final_action (F&& ff) noexcept : f{std::move (ff)} { }
1398+ explicit finally (const F& ff) noexcept : f{ff} { }
1399+ explicit finally (F&& ff) noexcept : f{std::move (ff)} { }
13921400
1393- ~final_action () noexcept { f (); }
1401+ ~finally () noexcept { f (); }
13941402
1395- final_action (final_action && that) noexcept
1403+ finally (finally && that) noexcept
13961404 : f(std::move(that.f)), invoke(std::exchange(that.invoke, false ))
13971405 { }
13981406
1399- final_action (final_action const &) = delete ;
1400- void operator =(final_action const &) = delete ;
1401- void operator =(final_action &&) = delete ;
1407+ finally (finally const &) = delete ;
1408+ void operator =(finally const &) = delete ;
1409+ void operator =(finally &&) = delete ;
14021410
14031411private:
14041412 F f;
14051413 bool invoke = true ;
14061414};
14071415
1408- [[nodiscard]] auto finally (auto && f) noexcept
1409- {
1410- return final_action<CPP2_TYPEOF (f)>{CPP2_FORWARD (f)};
1411- }
1412-
14131416
14141417// -----------------------------------------------------------------------
14151418//
0 commit comments