From 031dfa09f71e81cecda2ecc9d98b25eaf853eaa1 Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Mon, 8 Jan 2024 17:52:41 -0800 Subject: [PATCH] Issue 69 --- doc/leaf.adoc | 4 +- include/boost/leaf/error.hpp | 34 +++++++++++--- include/boost/leaf/on_error.hpp | 26 ++++++++--- meson.build | 44 +++++++++---------- test/Jamfile.v2 | 44 +++++++++---------- ...cpp => on_error_accumulate_basic_test.cpp} | 0 ...ccumulate_nested_error_exception_test.cpp} | 0 ...r_accumulate_nested_error_result_test.cpp} | 0 ...ulate_nested_new_error_exception_test.cpp} | 0 ...cumulate_nested_new_error_result_test.cpp} | 0 ...umulate_nested_success_exception_test.cpp} | 0 ...accumulate_nested_success_result_test.cpp} | 0 ...test.cpp => on_error_defer_basic_test.cpp} | 6 ++- ...ror_defer_nested_error_exception_test.cpp} | 0 ..._error_defer_nested_error_result_test.cpp} | 0 ...defer_nested_new_error_exception_test.cpp} | 0 ...or_defer_nested_new_error_result_test.cpp} | 0 ...r_defer_nested_success_exception_test.cpp} | 0 ...rror_defer_nested_success_result_test.cpp} | 0 ...st.cpp => on_error_preload_basic_test.cpp} | 0 ...pp => on_error_preload_exception_test.cpp} | 0 ...r_preload_nested_error_exception_test.cpp} | 0 ...rror_preload_nested_error_result_test.cpp} | 0 ...eload_nested_new_error_exception_test.cpp} | 0 ..._preload_nested_new_error_result_test.cpp} | 0 ...preload_nested_success_exception_test.cpp} | 0 ...or_preload_nested_success_result_test.cpp} | 0 27 files changed, 99 insertions(+), 59 deletions(-) rename test/{accumulate_basic_test.cpp => on_error_accumulate_basic_test.cpp} (100%) rename test/{accumulate_nested_error_exception_test.cpp => on_error_accumulate_nested_error_exception_test.cpp} (100%) rename test/{accumulate_nested_error_result_test.cpp => on_error_accumulate_nested_error_result_test.cpp} (100%) rename test/{accumulate_nested_new_error_exception_test.cpp => on_error_accumulate_nested_new_error_exception_test.cpp} (100%) rename test/{accumulate_nested_new_error_result_test.cpp => on_error_accumulate_nested_new_error_result_test.cpp} (100%) rename test/{accumulate_nested_success_exception_test.cpp => on_error_accumulate_nested_success_exception_test.cpp} (100%) rename test/{accumulate_nested_success_result_test.cpp => on_error_accumulate_nested_success_result_test.cpp} (100%) rename test/{defer_basic_test.cpp => on_error_defer_basic_test.cpp} (86%) rename test/{defer_nested_error_exception_test.cpp => on_error_defer_nested_error_exception_test.cpp} (100%) rename test/{defer_nested_error_result_test.cpp => on_error_defer_nested_error_result_test.cpp} (100%) rename test/{defer_nested_new_error_exception_test.cpp => on_error_defer_nested_new_error_exception_test.cpp} (100%) rename test/{defer_nested_new_error_result_test.cpp => on_error_defer_nested_new_error_result_test.cpp} (100%) rename test/{defer_nested_success_exception_test.cpp => on_error_defer_nested_success_exception_test.cpp} (100%) rename test/{defer_nested_success_result_test.cpp => on_error_defer_nested_success_result_test.cpp} (100%) rename test/{preload_basic_test.cpp => on_error_preload_basic_test.cpp} (100%) rename test/{preload_exception_test.cpp => on_error_preload_exception_test.cpp} (100%) rename test/{preload_nested_error_exception_test.cpp => on_error_preload_nested_error_exception_test.cpp} (100%) rename test/{preload_nested_error_result_test.cpp => on_error_preload_nested_error_result_test.cpp} (100%) rename test/{preload_nested_new_error_exception_test.cpp => on_error_preload_nested_new_error_exception_test.cpp} (100%) rename test/{preload_nested_new_error_result_test.cpp => on_error_preload_nested_new_error_result_test.cpp} (100%) rename test/{preload_nested_success_exception_test.cpp => on_error_preload_nested_success_exception_test.cpp} (100%) rename test/{preload_nested_success_result_test.cpp => on_error_preload_nested_success_result_test.cpp} (100%) diff --git a/doc/leaf.adoc b/doc/leaf.adoc index b120f95..8b9104d 100644 --- a/doc/leaf.adoc +++ b/doc/leaf.adoc @@ -3913,10 +3913,10 @@ namespace boost { namespace leaf { Requires: :: Each of the `Item...` types must be no-throw movable. Effects: :: -* If `value()==0`, all of `item...` are discarded and no further action is taken. +* If `thispass:[->]value()==0`, all of `item...` are discarded and no further action is taken. * Otherwise, what happens with each `item` depends on its type: ** If it is a function that takes a single argument of some type `E &`, that function is called with the object of type `E` currently associated with `*this`. If no such object exists, a default-initialized object is associated with `*this` and then passed to the function. -** If it is a function that takes no arguments, than function is called to obtain an error object, which is associated with `*this`. +** If it is a function that takes no arguments, that function is called to obtain an error object which is associated with `*this`, except in the special case of a `void` function, in which case it is invoked and no error object is obtained/loaded. ** Otherwise, the `item` itself is assumed to be an error object, which is associated with `*this`. Returns: :: `*this`. diff --git a/include/boost/leaf/error.hpp b/include/boost/leaf/error.hpp index b53794f..7f5dc9d 100644 --- a/include/boost/leaf/error.hpp +++ b/include/boost/leaf/error.hpp @@ -464,7 +464,7 @@ namespace leaf_detail } template - inline void dynamic_accumulate( int err_id, F && f ) noexcept(OnError) + inline void dynamic_load_accumulate( int err_id, F && f ) noexcept(OnError) { if( OnError ) { @@ -512,9 +512,9 @@ namespace leaf_detail template BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept(OnError) { - static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); - static_assert(!std::is_same::type, error_id>::value, "Error objects of type error_id are not allowed"); using T = typename std::decay::type; + static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); + static_assert(!std::is_same::value, "Error objects of type error_id are not allowed"); BOOST_LEAF_ASSERT((err_id&3)==1); if( slot * p = tls::read_ptr>() ) { @@ -529,7 +529,27 @@ namespace leaf_detail } template - BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept(OnError) + BOOST_LEAF_CONSTEXPR inline int load_slot_deferred( int err_id, F && f ) noexcept(OnError) + { + using E = typename function_traits::return_type; + using T = typename std::decay::type; + static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); + static_assert(!std::is_same::value, "Error objects of type error_id are not allowed"); + BOOST_LEAF_ASSERT((err_id&3)==1); + if( slot * p = tls::read_ptr>() ) + { + if( !OnError || !p->has_value(err_id) ) + (void) p->load(err_id, std::forward(f)()); + } +#if BOOST_LEAF_CFG_CAPTURE + else + dynamic_load(err_id, std::forward(f)()); +#endif + return 0; + } + + template + BOOST_LEAF_CONSTEXPR inline int load_slot_accumulate( int err_id, F && f ) noexcept(OnError) { static_assert(function_traits::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference"); using E = typename std::decay>::type; @@ -544,7 +564,7 @@ namespace leaf_detail } #if BOOST_LEAF_CFG_CAPTURE else - dynamic_accumulate(err_id, std::forward(f)); + dynamic_load_accumulate(err_id, std::forward(f)); #endif return 0; } @@ -578,7 +598,7 @@ namespace leaf_detail { BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept { - return load_slot(err_id, std::forward(f)()); + return load_slot_deferred(err_id, std::forward(f)); } }; @@ -587,7 +607,7 @@ namespace leaf_detail { BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept { - return accumulate_slot(err_id, std::forward(f)); + return load_slot_accumulate(err_id, std::forward(f)); } }; } diff --git a/include/boost/leaf/on_error.hpp b/include/boost/leaf/on_error.hpp index 2c5fde8..0218bb6 100644 --- a/include/boost/leaf/on_error.hpp +++ b/include/boost/leaf/on_error.hpp @@ -107,10 +107,9 @@ namespace leaf_detail } }; - template + template ::return_type> class deferred_item { - using E = decltype(std::declval()()); F f_; public: @@ -122,7 +121,25 @@ namespace leaf_detail BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { - (void) load_slot(err_id, f_()); + (void) load_slot_deferred(err_id, f_); + } + }; + + template + class deferred_item + { + F f_; + + public: + + BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept: + f_(std::forward(f)) + { + } + + BOOST_LEAF_CONSTEXPR void trigger( int ) noexcept + { + f_(); } }; @@ -132,7 +149,6 @@ namespace leaf_detail template class accumulating_item { - using E = A0; F f_; public: @@ -144,7 +160,7 @@ namespace leaf_detail BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { - accumulate_slot(err_id, std::move(f_)); + load_slot_accumulate(err_id, std::move(f_)); } }; diff --git a/meson.build b/meson.build index c7dd326..b6b92c3 100644 --- a/meson.build +++ b/meson.build @@ -104,13 +104,6 @@ leaf = declare_dependency( include_directories: 'include', compile_args: defines if option_enable_unit_tests tests = [ - 'accumulate_basic_test', - 'accumulate_nested_error_exception_test', - 'accumulate_nested_error_result_test', - 'accumulate_nested_new_error_exception_test', - 'accumulate_nested_new_error_result_test', - 'accumulate_nested_success_exception_test', - 'accumulate_nested_success_result_test', 'BOOST_LEAF_AUTO_test', 'BOOST_LEAF_ASSIGN_test', 'BOOST_LEAF_CHECK_test', @@ -129,13 +122,6 @@ if option_enable_unit_tests 'ctx_handle_some_test', 'ctx_remote_handle_all_test', 'ctx_remote_handle_some_test', - 'defer_basic_test', - 'defer_nested_error_exception_test', - 'defer_nested_error_result_test', - 'defer_nested_new_error_exception_test', - 'defer_nested_new_error_result_test', - 'defer_nested_success_exception_test', - 'defer_nested_success_result_test', 'diagnostic_info_test1', 'diagnostic_info_test2', 'diagnostic_info_test3', @@ -159,15 +145,29 @@ if option_enable_unit_tests 'match_member_test', 'match_value_test', 'multiple_errors_test', + 'on_error_accumulate_basic_test', + 'on_error_accumulate_nested_error_exception_test', + 'on_error_accumulate_nested_error_result_test', + 'on_error_accumulate_nested_new_error_exception_test', + 'on_error_accumulate_nested_new_error_result_test', + 'on_error_accumulate_nested_success_exception_test', + 'on_error_accumulate_nested_success_result_test', + 'on_error_defer_basic_test', + 'on_error_defer_nested_error_exception_test', + 'on_error_defer_nested_error_result_test', + 'on_error_defer_nested_new_error_exception_test', + 'on_error_defer_nested_new_error_result_test', + 'on_error_defer_nested_success_exception_test', + 'on_error_defer_nested_success_result_test', + 'on_error_preload_basic_test', + 'on_error_preload_exception_test', + 'on_error_preload_nested_error_exception_test', + 'on_error_preload_nested_error_result_test', + 'on_error_preload_nested_new_error_exception_test', + 'on_error_preload_nested_new_error_result_test', + 'on_error_preload_nested_success_exception_test', + 'on_error_preload_nested_success_result_test', 'optional_test', - 'preload_basic_test', - 'preload_exception_test', - 'preload_nested_error_exception_test', - 'preload_nested_error_result_test', - 'preload_nested_new_error_exception_test', - 'preload_nested_new_error_result_test', - 'preload_nested_success_exception_test', - 'preload_nested_success_result_test', 'print_test', 'result_bad_result_test', 'result_implicit_conversion_test', diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2a0986c..f12d0eb 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,13 +43,6 @@ compile _hpp_result_test.cpp ; compile _hpp_to_variant_test.cpp ; compile _hpp_leaf_test.cpp ; -run accumulate_basic_test.cpp ; -run accumulate_nested_error_exception_test.cpp ; -run accumulate_nested_error_result_test.cpp ; -run accumulate_nested_new_error_exception_test.cpp ; -run accumulate_nested_new_error_result_test.cpp ; -run accumulate_nested_success_exception_test.cpp ; -run accumulate_nested_success_result_test.cpp ; run BOOST_LEAF_AUTO_test.cpp ; run BOOST_LEAF_ASSIGN_test.cpp ; run BOOST_LEAF_CHECK_test.cpp ; @@ -69,13 +62,6 @@ run ctx_handle_all_test.cpp ; run ctx_handle_some_test.cpp ; run ctx_remote_handle_all_test.cpp ; run ctx_remote_handle_some_test.cpp ; -run defer_basic_test.cpp ; -run defer_nested_error_exception_test.cpp ; -run defer_nested_error_result_test.cpp ; -run defer_nested_new_error_exception_test.cpp ; -run defer_nested_new_error_result_test.cpp ; -run defer_nested_success_exception_test.cpp ; -run defer_nested_success_result_test.cpp ; run diagnostic_info_test1.cpp ; run diagnostic_info_test2.cpp ; run diagnostic_info_test3.cpp ; @@ -99,15 +85,29 @@ run match_test.cpp ; run match_member_test.cpp ; run match_value_test.cpp ; run multiple_errors_test.cpp ; +run on_error_accumulate_basic_test.cpp ; +run on_error_accumulate_nested_error_exception_test.cpp ; +run on_error_accumulate_nested_error_result_test.cpp ; +run on_error_accumulate_nested_new_error_exception_test.cpp ; +run on_error_accumulate_nested_new_error_result_test.cpp ; +run on_error_accumulate_nested_success_exception_test.cpp ; +run on_error_accumulate_nested_success_result_test.cpp ; +run on_error_defer_basic_test.cpp ; +run on_error_defer_nested_error_exception_test.cpp ; +run on_error_defer_nested_error_result_test.cpp ; +run on_error_defer_nested_new_error_exception_test.cpp ; +run on_error_defer_nested_new_error_result_test.cpp ; +run on_error_defer_nested_success_exception_test.cpp ; +run on_error_defer_nested_success_result_test.cpp ; +run on_error_preload_basic_test.cpp ; +run on_error_preload_exception_test.cpp ; +run on_error_preload_nested_error_exception_test.cpp ; +run on_error_preload_nested_error_result_test.cpp ; +run on_error_preload_nested_new_error_exception_test.cpp ; +run on_error_preload_nested_new_error_result_test.cpp ; +run on_error_preload_nested_success_exception_test.cpp ; +run on_error_preload_nested_success_result_test.cpp ; run optional_test.cpp ; -run preload_basic_test.cpp ; -run preload_exception_test.cpp ; -run preload_nested_error_exception_test.cpp ; -run preload_nested_error_result_test.cpp ; -run preload_nested_new_error_exception_test.cpp ; -run preload_nested_new_error_result_test.cpp ; -run preload_nested_success_exception_test.cpp ; -run preload_nested_success_result_test.cpp ; run print_test.cpp ; run result_bad_result_test.cpp ; run result_implicit_conversion_test.cpp ; diff --git a/test/accumulate_basic_test.cpp b/test/on_error_accumulate_basic_test.cpp similarity index 100% rename from test/accumulate_basic_test.cpp rename to test/on_error_accumulate_basic_test.cpp diff --git a/test/accumulate_nested_error_exception_test.cpp b/test/on_error_accumulate_nested_error_exception_test.cpp similarity index 100% rename from test/accumulate_nested_error_exception_test.cpp rename to test/on_error_accumulate_nested_error_exception_test.cpp diff --git a/test/accumulate_nested_error_result_test.cpp b/test/on_error_accumulate_nested_error_result_test.cpp similarity index 100% rename from test/accumulate_nested_error_result_test.cpp rename to test/on_error_accumulate_nested_error_result_test.cpp diff --git a/test/accumulate_nested_new_error_exception_test.cpp b/test/on_error_accumulate_nested_new_error_exception_test.cpp similarity index 100% rename from test/accumulate_nested_new_error_exception_test.cpp rename to test/on_error_accumulate_nested_new_error_exception_test.cpp diff --git a/test/accumulate_nested_new_error_result_test.cpp b/test/on_error_accumulate_nested_new_error_result_test.cpp similarity index 100% rename from test/accumulate_nested_new_error_result_test.cpp rename to test/on_error_accumulate_nested_new_error_result_test.cpp diff --git a/test/accumulate_nested_success_exception_test.cpp b/test/on_error_accumulate_nested_success_exception_test.cpp similarity index 100% rename from test/accumulate_nested_success_exception_test.cpp rename to test/on_error_accumulate_nested_success_exception_test.cpp diff --git a/test/accumulate_nested_success_result_test.cpp b/test/on_error_accumulate_nested_success_result_test.cpp similarity index 100% rename from test/accumulate_nested_success_result_test.cpp rename to test/on_error_accumulate_nested_success_result_test.cpp diff --git a/test/defer_basic_test.cpp b/test/on_error_defer_basic_test.cpp similarity index 86% rename from test/defer_basic_test.cpp rename to test/on_error_defer_basic_test.cpp index 1206363..ef48b6c 100644 --- a/test/defer_basic_test.cpp +++ b/test/on_error_defer_basic_test.cpp @@ -20,6 +20,8 @@ namespace leaf = boost::leaf; +int cleanup_count; + int global; int get_global() noexcept @@ -36,13 +38,14 @@ struct info leaf::error_id g() { global = 0; - auto load = leaf::on_error( []{ return info<42>{get_global()}; }, []{ return info<-42>{-42}; } ); + auto load = leaf::on_error( []{++cleanup_count;}, []{ return info<42>{get_global()}; }, []{ return info<-42>{-42}; } ); global = 42; return leaf::new_error(); } leaf::error_id f() { + auto load = leaf::on_error([]{++cleanup_count;}); return g(); } @@ -71,5 +74,6 @@ int main() return 2; } ); BOOST_TEST_EQ(r, 1); + BOOST_TEST_EQ(cleanup_count, 2); return boost::report_errors(); } diff --git a/test/defer_nested_error_exception_test.cpp b/test/on_error_defer_nested_error_exception_test.cpp similarity index 100% rename from test/defer_nested_error_exception_test.cpp rename to test/on_error_defer_nested_error_exception_test.cpp diff --git a/test/defer_nested_error_result_test.cpp b/test/on_error_defer_nested_error_result_test.cpp similarity index 100% rename from test/defer_nested_error_result_test.cpp rename to test/on_error_defer_nested_error_result_test.cpp diff --git a/test/defer_nested_new_error_exception_test.cpp b/test/on_error_defer_nested_new_error_exception_test.cpp similarity index 100% rename from test/defer_nested_new_error_exception_test.cpp rename to test/on_error_defer_nested_new_error_exception_test.cpp diff --git a/test/defer_nested_new_error_result_test.cpp b/test/on_error_defer_nested_new_error_result_test.cpp similarity index 100% rename from test/defer_nested_new_error_result_test.cpp rename to test/on_error_defer_nested_new_error_result_test.cpp diff --git a/test/defer_nested_success_exception_test.cpp b/test/on_error_defer_nested_success_exception_test.cpp similarity index 100% rename from test/defer_nested_success_exception_test.cpp rename to test/on_error_defer_nested_success_exception_test.cpp diff --git a/test/defer_nested_success_result_test.cpp b/test/on_error_defer_nested_success_result_test.cpp similarity index 100% rename from test/defer_nested_success_result_test.cpp rename to test/on_error_defer_nested_success_result_test.cpp diff --git a/test/preload_basic_test.cpp b/test/on_error_preload_basic_test.cpp similarity index 100% rename from test/preload_basic_test.cpp rename to test/on_error_preload_basic_test.cpp diff --git a/test/preload_exception_test.cpp b/test/on_error_preload_exception_test.cpp similarity index 100% rename from test/preload_exception_test.cpp rename to test/on_error_preload_exception_test.cpp diff --git a/test/preload_nested_error_exception_test.cpp b/test/on_error_preload_nested_error_exception_test.cpp similarity index 100% rename from test/preload_nested_error_exception_test.cpp rename to test/on_error_preload_nested_error_exception_test.cpp diff --git a/test/preload_nested_error_result_test.cpp b/test/on_error_preload_nested_error_result_test.cpp similarity index 100% rename from test/preload_nested_error_result_test.cpp rename to test/on_error_preload_nested_error_result_test.cpp diff --git a/test/preload_nested_new_error_exception_test.cpp b/test/on_error_preload_nested_new_error_exception_test.cpp similarity index 100% rename from test/preload_nested_new_error_exception_test.cpp rename to test/on_error_preload_nested_new_error_exception_test.cpp diff --git a/test/preload_nested_new_error_result_test.cpp b/test/on_error_preload_nested_new_error_result_test.cpp similarity index 100% rename from test/preload_nested_new_error_result_test.cpp rename to test/on_error_preload_nested_new_error_result_test.cpp diff --git a/test/preload_nested_success_exception_test.cpp b/test/on_error_preload_nested_success_exception_test.cpp similarity index 100% rename from test/preload_nested_success_exception_test.cpp rename to test/on_error_preload_nested_success_exception_test.cpp diff --git a/test/preload_nested_success_result_test.cpp b/test/on_error_preload_nested_success_result_test.cpp similarity index 100% rename from test/preload_nested_success_result_test.cpp rename to test/on_error_preload_nested_success_result_test.cpp