diff --git a/benchmark/deep_stack_leaf.cpp b/benchmark/deep_stack_leaf.cpp index 9fd15c7..ebd9fe3 100644 --- a/benchmark/deep_stack_leaf.cpp +++ b/benchmark/deep_stack_leaf.cpp @@ -6,23 +6,23 @@ // See benchmark.md #ifndef BOOST_LEAF_ALL_HPP_INCLUDED -# include +# include #endif #ifndef BOOST_LEAF_NO_EXCEPTIONS -# error Please disable exception handling. +# error Please disable exception handling. #endif #if BOOST_LEAF_DIAGNOSTICS -# error Please disable diagnostics. +# error Please disable diagnostics. #endif #ifdef _MSC_VER -# define NOINLINE __declspec(noinline) -# define ALWAYS_INLINE __forceinline +# define NOINLINE __declspec(noinline) +# define ALWAYS_INLINE __forceinline #else -# define NOINLINE __attribute__((noinline)) -# define ALWAYS_INLINE __attribute__((always_inline)) inline +# define NOINLINE __attribute__((noinline)) +# define ALWAYS_INLINE __attribute__((always_inline)) inline #endif #include @@ -39,17 +39,17 @@ namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } ////////////////////////////////////// @@ -62,18 +62,18 @@ namespace leaf = boost::leaf; enum class e_error_code { - ec0, ec1, ec2, ec3 + ec0, ec1, ec2, ec3 }; struct e_system_error { - int value; - std::string what; + int value; + std::string what; }; struct e_heavy_payload { - std::array value; + std::array value; }; template @@ -82,60 +82,60 @@ leaf::error_id make_error() noexcept; template <> inline leaf::error_id make_error() noexcept { - switch(std::rand()%4) - { - default: return leaf::new_error(e_error_code::ec0); - case 1: return leaf::new_error(e_error_code::ec1); - case 2: return leaf::new_error(e_error_code::ec2); - case 3: return leaf::new_error(e_error_code::ec3); - } + switch(std::rand()%4) + { + default: return leaf::new_error(e_error_code::ec0); + case 1: return leaf::new_error(e_error_code::ec1); + case 2: return leaf::new_error(e_error_code::ec2); + case 3: return leaf::new_error(e_error_code::ec3); + } } template <> inline leaf::error_id make_error() noexcept { - return std::error_code(std::rand(), std::system_category()); + return std::error_code(std::rand(), std::system_category()); } template <> inline leaf::error_id make_error() noexcept { - return leaf::new_error( e_system_error { std::rand(), std::string(std::rand()%32, ' ') } ); + return leaf::new_error( e_system_error { std::rand(), std::string(std::rand()%32, ' ') } ); } template <> inline leaf::error_id make_error() noexcept { - e_heavy_payload e; - std::fill(e.value.begin(), e.value.end(), std::rand()); - return leaf::new_error(e); + e_heavy_payload e; + std::fill(e.value.begin(), e.value.end(), std::rand()); + return leaf::new_error(e); } inline bool should_fail( int failure_rate ) noexcept { - assert(failure_rate>=0); - assert(failure_rate<=100); - return (std::rand()%100) < failure_rate; + assert(failure_rate>=0); + assert(failure_rate<=100); + return (std::rand()%100) < failure_rate; } inline int handle_error( e_error_code e ) noexcept { - return int(e); + return int(e); } inline int handle_error( std::error_code const & e ) noexcept { - return e.value(); + return e.value(); } inline int handle_error( e_system_error const & e ) noexcept { - return e.value + e.what.size(); + return e.value + e.what.size(); } inline int handle_error( e_heavy_payload const & e ) noexcept { - return std::accumulate(e.value.begin(), e.value.end(), 0); + return std::accumulate(e.value.begin(), e.value.end(), 0); } ////////////////////////////////////// @@ -148,13 +148,13 @@ struct select_result_type; template struct select_result_type { - using type = leaf::result; // Does not depend on E + using type = leaf::result; // Does not depend on E }; template struct select_result_type { - using type = leaf::result; // Does not depend on E + using type = leaf::result; // Does not depend on E }; template @@ -165,27 +165,27 @@ using select_result_t = typename select_result_type::type; template struct benchmark { - using e_type = E; + using e_type = E; - NOINLINE static select_result_t f( int failure_rate ) noexcept - { - BOOST_LEAF_AUTO(x, (benchmark::f(failure_rate))); - return x+1; - } + NOINLINE static select_result_t f( int failure_rate ) noexcept + { + BOOST_LEAF_AUTO(x, (benchmark::f(failure_rate))); + return x+1; + } }; template struct benchmark<1, E> { - using e_type = E; + using e_type = E; - NOINLINE static select_result_t<1, E> f( int failure_rate ) noexcept - { - if( should_fail(failure_rate) ) - return make_error(); - else - return std::rand(); - } + NOINLINE static select_result_t<1, E> f( int failure_rate ) noexcept + { + if( should_fail(failure_rate) ) + return make_error(); + else + return std::rand(); + } }; ////////////////////////////////////// @@ -193,50 +193,50 @@ struct benchmark<1, E> template NOINLINE int runner( int failure_rate ) noexcept { - return leaf::try_handle_all( - [=] - { - return Benchmark::f(failure_rate); - }, - []( typename Benchmark::e_type const & e ) - { - return handle_error(e); - }, - [] - { - return -1; - } ); + return leaf::try_handle_all( + [=] + { + return Benchmark::f(failure_rate); + }, + []( typename Benchmark::e_type const & e ) + { + return handle_error(e); + }, + [] + { + return -1; + } ); } ////////////////////////////////////// std::fstream append_csv() { - if( FILE * f = fopen("benchmark.csv","rb") ) - { - fclose(f); - return std::fstream("benchmark.csv", std::fstream::out | std::fstream::app); - } - else - { - std::fstream fs("benchmark.csv", std::fstream::out | std::fstream::app); - fs << "\"Result Type\",2%,98%\n"; - return fs; - } + if( FILE * f = fopen("benchmark.csv","rb") ) + { + fclose(f); + return std::fstream("benchmark.csv", std::fstream::out | std::fstream::app); + } + else + { + std::fstream fs("benchmark.csv", std::fstream::out | std::fstream::app); + fs << "\"Result Type\",2%,98%\n"; + return fs; + } } template int print_elapsed_time( int iteration_count, F && f ) { - auto start = std::chrono::steady_clock::now(); - int val = 0; - for( int i = 0; i!=iteration_count; ++i ) - val += std::forward(f)(); - auto stop = std::chrono::steady_clock::now(); - int elapsed = std::chrono::duration_cast(stop-start).count(); - std::cout << std::right << std::setw(9) << elapsed; - append_csv() << ',' << elapsed; - return val; + auto start = std::chrono::steady_clock::now(); + int val = 0; + for( int i = 0; i!=iteration_count; ++i ) + val += std::forward(f)(); + auto stop = std::chrono::steady_clock::now(); + int elapsed = std::chrono::duration_cast(stop-start).count(); + std::cout << std::right << std::setw(9) << elapsed; + append_csv() << ',' << elapsed; + return val; } ////////////////////////////////////// @@ -244,35 +244,35 @@ int print_elapsed_time( int iteration_count, F && f ) template int benchmark_type( char const * type_name, int iteration_count ) { - int x=0; - append_csv() << "\"" USING_RESULT_TYPE "\""; - std::cout << '\n' << std::left << std::setw(16) << type_name << '|'; - std::srand(0); - x += print_elapsed_time( iteration_count, [] { return runner>(2); } ); - std::cout << " |"; - std::srand(0); - x += print_elapsed_time( iteration_count, [] { return runner>(98); } ); - append_csv() << '\n'; - return x; + int x=0; + append_csv() << "\"" USING_RESULT_TYPE "\""; + std::cout << '\n' << std::left << std::setw(16) << type_name << '|'; + std::srand(0); + x += print_elapsed_time( iteration_count, [] { return runner>(2); } ); + std::cout << " |"; + std::srand(0); + x += print_elapsed_time( iteration_count, [] { return runner>(98); } ); + append_csv() << '\n'; + return x; } ////////////////////////////////////// int main() { - int const depth = 10; - int const iteration_count = 10000000; - std::cout << - iteration_count << " iterations, call depth " << depth << ", sizeof(e_heavy_payload) = " << sizeof(e_heavy_payload) << "\n" - USING_RESULT_TYPE "\n" - "Error type | 2% (μs) | 98% (μs)\n" - "----------------|----------|---------"; - int r = 0; - r += benchmark_type("e_error_code", iteration_count); - r += benchmark_type("std::error_code", iteration_count); - r += benchmark_type("e_system_error", iteration_count); - r += benchmark_type("e_heavy_payload", iteration_count); - std::cout << '\n'; - // std::cout << std::rand() << '\n'; - return r; + int const depth = 10; + int const iteration_count = 10000000; + std::cout << + iteration_count << " iterations, call depth " << depth << ", sizeof(e_heavy_payload) = " << sizeof(e_heavy_payload) << "\n" + USING_RESULT_TYPE "\n" + "Error type | 2% (μs) | 98% (μs)\n" + "----------------|----------|---------"; + int r = 0; + r += benchmark_type("e_error_code", iteration_count); + r += benchmark_type("std::error_code", iteration_count); + r += benchmark_type("e_system_error", iteration_count); + r += benchmark_type("e_heavy_payload", iteration_count); + std::cout << '\n'; + // std::cout << std::rand() << '\n'; + return r; } diff --git a/benchmark/deep_stack_other.cpp b/benchmark/deep_stack_other.cpp index da3bc3c..4fa07f1 100644 --- a/benchmark/deep_stack_other.cpp +++ b/benchmark/deep_stack_other.cpp @@ -6,41 +6,41 @@ // See benchmark.md #ifndef BENCHMARK_WHAT -# define BENCHMARK_WHAT 0 +# define BENCHMARK_WHAT 0 #endif #if BENCHMARK_WHAT == 0 -# ifndef TL_EXPECTED_HPP -# include "tl/expected.hpp" -# endif -# define BENCHMARK_SUCCESS(e) e -# define BENCHMARK_FAILURE(e) tl::make_unexpected(e) -# define BENCHMARK_TRY(v,r)\ - auto && _r_##v = r;\ - if( !_r_##v )\ - return BENCHMARK_FAILURE(_r_##v.error());\ - auto && v = _r_##v.value() +# ifndef TL_EXPECTED_HPP +# include "tl/expected.hpp" +# endif +# define BENCHMARK_SUCCESS(e) e +# define BENCHMARK_FAILURE(e) tl::make_unexpected(e) +# define BENCHMARK_TRY(v,r)\ + auto && _r_##v = r;\ + if( !_r_##v )\ + return BENCHMARK_FAILURE(_r_##v.error());\ + auto && v = _r_##v.value() #else -# include -# include -# define BENCHMARK_SUCCESS(e) boost::outcome_v2::success(e) -# define BENCHMARK_FAILURE(e) boost::outcome_v2::failure(e) -# define BENCHMARK_TRY BOOST_OUTCOME_TRY -# ifndef BOOST_NO_EXCEPTIONS -# error Please disable exception handling. -# endif +# include +# include +# define BENCHMARK_SUCCESS(e) boost::outcome_v2::success(e) +# define BENCHMARK_FAILURE(e) boost::outcome_v2::failure(e) +# define BENCHMARK_TRY BOOST_OUTCOME_TRY +# ifndef BOOST_NO_EXCEPTIONS +# error Please disable exception handling. +# endif #endif #ifdef _MSC_VER -# define NOINLINE __declspec(noinline) -# define ALWAYS_INLINE __forceinline +# define NOINLINE __declspec(noinline) +# define ALWAYS_INLINE __forceinline #else -# define NOINLINE __attribute__((noinline)) -# define ALWAYS_INLINE __attribute__((always_inline)) inline +# define NOINLINE __attribute__((noinline)) +# define ALWAYS_INLINE __attribute__((always_inline)) inline #endif #include @@ -57,62 +57,62 @@ namespace boost { - void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } ////////////////////////////////////// #if BENCHMARK_WHAT == 0 // tl::expected -# define USING_RESULT_TYPE "tl::expected" +# define USING_RESULT_TYPE "tl::expected" - template - using result = tl::expected; + template + using result = tl::expected; #elif BENCHMARK_WHAT == 1 // outcome::result -# define USING_RESULT_TYPE "outcome::result" +# define USING_RESULT_TYPE "outcome::result" - template - using result = boost::outcome_v2::std_result; + template + using result = boost::outcome_v2::std_result; #elif BENCHMARK_WHAT == 2 // outcome::outcome -# define USING_RESULT_TYPE "outcome::outcome" +# define USING_RESULT_TYPE "outcome::outcome" - template - using result = boost::outcome_v2::std_outcome; + template + using result = boost::outcome_v2::std_outcome; #else -# error Benchmark what? +# error Benchmark what? #endif ////////////////////////////////////// enum class e_error_code { - ec0, ec1, ec2, ec3 + ec0, ec1, ec2, ec3 }; struct e_system_error { - int value; - std::string what; + int value; + std::string what; }; struct e_heavy_payload { - std::array value; + std::array value; }; template @@ -121,60 +121,60 @@ E make_error() noexcept; template <> inline e_error_code make_error() noexcept { - switch(std::rand()%4) - { - default: return e_error_code::ec0; - case 1: return e_error_code::ec1; - case 2: return e_error_code::ec2; - case 3: return e_error_code::ec3; - } + switch(std::rand()%4) + { + default: return e_error_code::ec0; + case 1: return e_error_code::ec1; + case 2: return e_error_code::ec2; + case 3: return e_error_code::ec3; + } } template <> inline std::error_code make_error() noexcept { - return std::error_code(std::rand(), std::system_category()); + return std::error_code(std::rand(), std::system_category()); } template <> inline e_system_error make_error() noexcept { - return { std::rand(), std::string(std::rand()%32, ' ') }; + return { std::rand(), std::string(std::rand()%32, ' ') }; } template <> inline e_heavy_payload make_error() noexcept { - e_heavy_payload e; - std::fill(e.value.begin(), e.value.end(), std::rand()); - return e; + e_heavy_payload e; + std::fill(e.value.begin(), e.value.end(), std::rand()); + return e; } inline bool should_fail( int failure_rate ) noexcept { - assert(failure_rate>=0); - assert(failure_rate<=100); - return (std::rand()%100) < failure_rate; + assert(failure_rate>=0); + assert(failure_rate<=100); + return (std::rand()%100) < failure_rate; } inline int handle_error( e_error_code e ) noexcept { - return int(e); + return int(e); } inline int handle_error( std::error_code const & e ) noexcept { - return e.value(); + return e.value(); } inline int handle_error( e_system_error const & e ) noexcept { - return e.value + e.what.size(); + return e.value + e.what.size(); } inline int handle_error( e_heavy_payload const & e ) noexcept { - return std::accumulate(e.value.begin(), e.value.end(), 0); + return std::accumulate(e.value.begin(), e.value.end(), 0); } ////////////////////////////////////// @@ -187,13 +187,13 @@ struct select_result_type; template struct select_result_type { - using type = result; + using type = result; }; template struct select_result_type { - using type = result; + using type = result; }; template @@ -204,27 +204,27 @@ using select_result_t = typename select_result_type::type; template struct benchmark { - using e_type = E; + using e_type = E; - NOINLINE static select_result_t f( int failure_rate ) noexcept - { - BENCHMARK_TRY(x, (benchmark::f(failure_rate))); - return BENCHMARK_SUCCESS(x+1); - } + NOINLINE static select_result_t f( int failure_rate ) noexcept + { + BENCHMARK_TRY(x, (benchmark::f(failure_rate))); + return BENCHMARK_SUCCESS(x+1); + } }; template struct benchmark<1, E> { - using e_type = E; + using e_type = E; - NOINLINE static select_result_t<1, E> f( int failure_rate ) noexcept - { - if( should_fail(failure_rate) ) - return BENCHMARK_FAILURE(make_error()); - else - return BENCHMARK_SUCCESS(std::rand()); - } + NOINLINE static select_result_t<1, E> f( int failure_rate ) noexcept + { + if( should_fail(failure_rate) ) + return BENCHMARK_FAILURE(make_error()); + else + return BENCHMARK_SUCCESS(std::rand()); + } }; ////////////////////////////////////// @@ -232,41 +232,41 @@ struct benchmark<1, E> template NOINLINE int runner( int failure_rate ) noexcept { - if( auto r = Benchmark::f(failure_rate) ) - return r.value(); - else - return handle_error(r.error()); + if( auto r = Benchmark::f(failure_rate) ) + return r.value(); + else + return handle_error(r.error()); } ////////////////////////////////////// std::fstream append_csv() { - if( FILE * f = fopen("benchmark.csv","rb") ) - { - fclose(f); - return std::fstream("benchmark.csv", std::fstream::out | std::fstream::app); - } - else - { - std::fstream fs("benchmark.csv", std::fstream::out | std::fstream::app); - fs << "\"Result Type\",2%,98%\n"; - return fs; - } + if( FILE * f = fopen("benchmark.csv","rb") ) + { + fclose(f); + return std::fstream("benchmark.csv", std::fstream::out | std::fstream::app); + } + else + { + std::fstream fs("benchmark.csv", std::fstream::out | std::fstream::app); + fs << "\"Result Type\",2%,98%\n"; + return fs; + } } template int print_elapsed_time( int iteration_count, F && f ) { - auto start = std::chrono::steady_clock::now(); - int val = 0; - for( int i = 0; i!=iteration_count; ++i ) - val += std::forward(f)(); - auto stop = std::chrono::steady_clock::now(); - int elapsed = std::chrono::duration_cast(stop-start).count(); - std::cout << std::right << std::setw(9) << elapsed; - append_csv() << ',' << elapsed; - return val; + auto start = std::chrono::steady_clock::now(); + int val = 0; + for( int i = 0; i!=iteration_count; ++i ) + val += std::forward(f)(); + auto stop = std::chrono::steady_clock::now(); + int elapsed = std::chrono::duration_cast(stop-start).count(); + std::cout << std::right << std::setw(9) << elapsed; + append_csv() << ',' << elapsed; + return val; } ////////////////////////////////////// @@ -274,35 +274,35 @@ int print_elapsed_time( int iteration_count, F && f ) template int benchmark_type( char const * type_name, int iteration_count ) { - int x=0; - append_csv() << "\"" USING_RESULT_TYPE "\""; - std::cout << '\n' << std::left << std::setw(16) << type_name << '|'; - std::srand(0); - x += print_elapsed_time( iteration_count, [] { return runner>(2); } ); - std::cout << " |"; - std::srand(0); - x += print_elapsed_time( iteration_count, [] { return runner>(98); } ); - append_csv() << '\n'; - return x; + int x=0; + append_csv() << "\"" USING_RESULT_TYPE "\""; + std::cout << '\n' << std::left << std::setw(16) << type_name << '|'; + std::srand(0); + x += print_elapsed_time( iteration_count, [] { return runner>(2); } ); + std::cout << " |"; + std::srand(0); + x += print_elapsed_time( iteration_count, [] { return runner>(98); } ); + append_csv() << '\n'; + return x; } ////////////////////////////////////// int main() { - int const depth = 10; - int const iteration_count = 10000000; - std::cout << - iteration_count << " iterations, call depth " << depth << ", sizeof(e_heavy_payload) = " << sizeof(e_heavy_payload) << "\n" - USING_RESULT_TYPE "\n" - "Error type | 2% (μs) | 98% (μs)\n" - "----------------|----------|---------"; - int r = 0; - r += benchmark_type("e_error_code", iteration_count); - r += benchmark_type("std::error_code", iteration_count); - r += benchmark_type("e_system_error", iteration_count); - r += benchmark_type("e_heavy_payload", iteration_count); - std::cout << '\n'; - // std::cout << std::rand() << '\n'; - return r; + int const depth = 10; + int const iteration_count = 10000000; + std::cout << + iteration_count << " iterations, call depth " << depth << ", sizeof(e_heavy_payload) = " << sizeof(e_heavy_payload) << "\n" + USING_RESULT_TYPE "\n" + "Error type | 2% (μs) | 98% (μs)\n" + "----------------|----------|---------"; + int r = 0; + r += benchmark_type("e_error_code", iteration_count); + r += benchmark_type("std::error_code", iteration_count); + r += benchmark_type("e_system_error", iteration_count); + r += benchmark_type("e_heavy_payload", iteration_count); + std::cout << '\n'; + // std::cout << std::rand() << '\n'; + return r; } diff --git a/examples/capture_in_exception.cpp b/examples/capture_in_exception.cpp index 83fa73f..1c6e3ae 100644 --- a/examples/capture_in_exception.cpp +++ b/examples/capture_in_exception.cpp @@ -30,69 +30,69 @@ struct task_result { }; // This is our task function. It produces objects of type task_result, but it may fail... task_result task() { - bool succeed = (rand()%4) != 0; //...at random. - if( succeed ) - return { }; - else - throw leaf::exception( - e_thread_id{std::this_thread::get_id()}, - e_failure_info1{"info"}, - e_failure_info2{42} ); + bool succeed = (rand()%4) != 0; //...at random. + if( succeed ) + return { }; + else + throw leaf::exception( + e_thread_id{std::this_thread::get_id()}, + e_failure_info1{"info"}, + e_failure_info2{42} ); }; int main() { - int const task_count = 42; + int const task_count = 42; - // The error_handlers are used in this thread (see leaf::try_catch below). The - // arguments passed to individual lambdas are transported from the worker thread - // to the main thread automatically. - auto error_handlers = std::make_tuple( - []( e_failure_info1 const & v1, e_failure_info2 const & v2, e_thread_id const & tid ) - { - std::cerr << "Error in thread " << tid.value << "! failure_info1: " << v1.value << ", failure_info2: " << v2.value << std::endl; - }, - []( leaf::diagnostic_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - } ); + // The error_handlers are used in this thread (see leaf::try_catch below). The + // arguments passed to individual lambdas are transported from the worker thread + // to the main thread automatically. + auto error_handlers = std::make_tuple( + []( e_failure_info1 const & v1, e_failure_info2 const & v2, e_thread_id const & tid ) + { + std::cerr << "Error in thread " << tid.value << "! failure_info1: " << v1.value << ", failure_info2: " << v2.value << std::endl; + }, + []( leaf::diagnostic_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + } ); - // Container to collect the generated std::future objects. - std::vector> fut; + // Container to collect the generated std::future objects. + std::vector> fut; - // Launch the tasks, but rather than launching the task function directly, we launch a - // wrapper function which calls leaf::capture, passing a context object that will hold - // the error objects reported from the task in case it throws. The error types the - // context is able to hold statically are automatically deduced from the type of the - // error_handlers tuple. - std::generate_n( std::back_inserter(fut), task_count, - [&] - { - return std::async( - std::launch::async, - [&] - { - return leaf::capture(leaf::make_shared_context(error_handlers), &task); - } ); - } ); + // Launch the tasks, but rather than launching the task function directly, we launch a + // wrapper function which calls leaf::capture, passing a context object that will hold + // the error objects reported from the task in case it throws. The error types the + // context is able to hold statically are automatically deduced from the type of the + // error_handlers tuple. + std::generate_n( std::back_inserter(fut), task_count, + [&] + { + return std::async( + std::launch::async, + [&] + { + return leaf::capture(leaf::make_shared_context(error_handlers), &task); + } ); + } ); - // Wait on the futures, get the task results, handle errors. - for( auto & f : fut ) - { - f.wait(); + // Wait on the futures, get the task results, handle errors. + for( auto & f : fut ) + { + f.wait(); - leaf::try_catch( - [&] - { - task_result r = f.get(); + leaf::try_catch( + [&] + { + task_result r = f.get(); - // Success! Use r to access task_result. - std::cout << "Success!" << std::endl; - (void) r; // Presumably we'll somehow use the task_result. - }, - error_handlers ); - } + // Success! Use r to access task_result. + std::cout << "Success!" << std::endl; + (void) r; // Presumably we'll somehow use the task_result. + }, + error_handlers ); + } } diff --git a/examples/capture_in_result.cpp b/examples/capture_in_result.cpp index c1a9be7..906fe43 100644 --- a/examples/capture_in_result.cpp +++ b/examples/capture_in_result.cpp @@ -30,72 +30,72 @@ struct task_result { }; // This is our task function. It produces objects of type task_result, but it may fail... leaf::result task() { - bool succeed = (rand()%4) != 0; //...at random. - if( succeed ) - return { }; - else - return leaf::new_error( - e_thread_id{std::this_thread::get_id()}, - e_failure_info1{"info"}, - e_failure_info2{42} ); + bool succeed = (rand()%4) != 0; //...at random. + if( succeed ) + return { }; + else + return leaf::new_error( + e_thread_id{std::this_thread::get_id()}, + e_failure_info1{"info"}, + e_failure_info2{42} ); }; int main() { - int const task_count = 42; + int const task_count = 42; - // The error_handlers are used in this thread (see leaf::try_handle_all below). The - // arguments passed to individual lambdas are transported from the worker thread - // to the main thread automatically. - auto error_handlers = std::make_tuple( - []( e_failure_info1 const & v1, e_failure_info2 const & v2, e_thread_id const & tid ) - { - std::cerr << "Error in thread " << tid.value << "! failure_info1: " << v1.value << ", failure_info2: " << v2.value << std::endl; - }, - []( leaf::diagnostic_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - } ); + // The error_handlers are used in this thread (see leaf::try_handle_all below). The + // arguments passed to individual lambdas are transported from the worker thread + // to the main thread automatically. + auto error_handlers = std::make_tuple( + []( e_failure_info1 const & v1, e_failure_info2 const & v2, e_thread_id const & tid ) + { + std::cerr << "Error in thread " << tid.value << "! failure_info1: " << v1.value << ", failure_info2: " << v2.value << std::endl; + }, + []( leaf::diagnostic_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + } ); - // Container to collect the generated std::future objects. - std::vector>> fut; + // Container to collect the generated std::future objects. + std::vector>> fut; - // Launch the tasks, but rather than launching the task function directly, we launch a - // wrapper function which calls leaf::capture, passing a context object that will hold - // the error objects reported from the task in case of an error. The error types the - // context is able to hold statically are automatically deduced from the type of the - // error_handlers tuple. - std::generate_n( std::back_inserter(fut), task_count, - [&] - { - return std::async( - std::launch::async, - [&] - { - return leaf::capture(leaf::make_shared_context(error_handlers), &task); - } ); - } ); + // Launch the tasks, but rather than launching the task function directly, we launch a + // wrapper function which calls leaf::capture, passing a context object that will hold + // the error objects reported from the task in case of an error. The error types the + // context is able to hold statically are automatically deduced from the type of the + // error_handlers tuple. + std::generate_n( std::back_inserter(fut), task_count, + [&] + { + return std::async( + std::launch::async, + [&] + { + return leaf::capture(leaf::make_shared_context(error_handlers), &task); + } ); + } ); - // Wait on the futures, get the task results, handle errors. - for( auto & f : fut ) - { - f.wait(); + // Wait on the futures, get the task results, handle errors. + for( auto & f : fut ) + { + f.wait(); - leaf::try_handle_all( - [&]() -> leaf::result - { - BOOST_LEAF_AUTO(r,f.get()); + leaf::try_handle_all( + [&]() -> leaf::result + { + BOOST_LEAF_AUTO(r,f.get()); - // Success! Use r to access task_result. - std::cout << "Success!" << std::endl; - (void) r; // Presumably we'll somehow use the task_result. - return { }; - }, - error_handlers ); - } + // Success! Use r to access task_result. + std::cout << "Success!" << std::endl; + (void) r; // Presumably we'll somehow use the task_result. + return { }; + }, + error_handlers ); + } } //////////////////////////////////////// @@ -104,17 +104,17 @@ int main() namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/error_log.cpp b/examples/error_log.cpp index 54e37d6..b3f72a1 100644 --- a/examples/error_log.cpp +++ b/examples/error_log.cpp @@ -25,27 +25,27 @@ namespace leaf = boost::leaf; // The error log is activated only if an error-handling scope provides a handler for e_error_log. struct e_error_log { - struct rec - { - char const * file; - int line; - friend std::ostream & operator<<( std::ostream & os, rec const & x ) - { - return os << x.file << '(' << x.line << ')'; - } - }; + struct rec + { + char const * file; + int line; + friend std::ostream & operator<<( std::ostream & os, rec const & x ) + { + return os << x.file << '(' << x.line << ')'; + } + }; - e_error_log() - { - std::cerr << "Error! Log:" << std::endl; - } + e_error_log() + { + std::cerr << "Error! Log:" << std::endl; + } - // Our e_error_log instance is stateless, used only as a target to operator<<. - template - friend std::ostream & operator<<( e_error_log const &, T const & x ) - { - return std::cerr << x << std::endl; - } + // Our e_error_log instance is stateless, used only as a target to operator<<. + template + friend std::ostream & operator<<( e_error_log const &, T const & x ) + { + return std::cerr << x << std::endl; + } }; // The ERROR_LOG macro is designed for use in functions that detect or forward errors @@ -60,70 +60,70 @@ int const failure_percent = 25; leaf::result f1() { - ERROR_LOG; - if( (std::rand()%100) > failure_percent ) - return { }; - else - return leaf::new_error(); + ERROR_LOG; + if( (std::rand()%100) > failure_percent ) + return { }; + else + return leaf::new_error(); } leaf::result f2() { - ERROR_LOG; - if( (std::rand()%100) > failure_percent ) - return f1(); - else - return leaf::new_error(); + ERROR_LOG; + if( (std::rand()%100) > failure_percent ) + return f1(); + else + return leaf::new_error(); } leaf::result f3() { - ERROR_LOG; - if( (std::rand()%100) > failure_percent ) - return f2(); - else - return leaf::new_error(); + ERROR_LOG; + if( (std::rand()%100) > failure_percent ) + return f2(); + else + return leaf::new_error(); } leaf::result f4() { - ERROR_LOG; - if( (std::rand()%100) > failure_percent ) - return f3(); - else - return leaf::new_error(); + ERROR_LOG; + if( (std::rand()%100) > failure_percent ) + return f3(); + else + return leaf::new_error(); } leaf::result f5() { - ERROR_LOG; - if( (std::rand()%100) > failure_percent ) - return f4(); - else - return leaf::new_error(); + ERROR_LOG; + if( (std::rand()%100) > failure_percent ) + return f4(); + else + return leaf::new_error(); } int main() { - for( int i=0; i!=10; ++i ) - leaf::try_handle_all( - [&]() -> leaf::result - { - std::cout << "Run # " << i << ": "; - BOOST_LEAF_CHECK(f5()); - std::cout << "Success!" << std::endl; - return { }; - }, + for( int i=0; i!=10; ++i ) + leaf::try_handle_all( + [&]() -> leaf::result + { + std::cout << "Run # " << i << ": "; + BOOST_LEAF_CHECK(f5()); + std::cout << "Success!" << std::endl; + return { }; + }, #if ENABLE_ERROR_LOG // This single #if enables or disables the printing of the error log. - []( e_error_log const & ) - { - }, + []( e_error_log const & ) + { + }, #endif - [] - { - std::cerr << "Error!" << std::endl; - } ); - return 0; + [] + { + std::cerr << "Error!" << std::endl; + } ); + return 0; } //////////////////////////////////////// @@ -132,17 +132,17 @@ int main() namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/error_trace.cpp b/examples/error_trace.cpp index 3f55c4f..ae6b96c 100644 --- a/examples/error_trace.cpp +++ b/examples/error_trace.cpp @@ -26,24 +26,24 @@ namespace leaf = boost::leaf; // The error trace is activated only if an error-handling scope provides a handler for e_error_trace. struct e_error_trace { - struct rec - { - char const * file; - int line; - friend std::ostream & operator<<( std::ostream & os, rec const & x ) - { - return os << x.file << '(' << x.line << ')' << std::endl; - } - }; + struct rec + { + char const * file; + int line; + friend std::ostream & operator<<( std::ostream & os, rec const & x ) + { + return os << x.file << '(' << x.line << ')' << std::endl; + } + }; - std::deque value; + std::deque value; - friend std::ostream & operator<<( std::ostream & os, e_error_trace const & tr ) - { - for( auto & i : tr.value ) - os << i; - return os; - } + friend std::ostream & operator<<( std::ostream & os, e_error_trace const & tr ) + { + for( auto & i : tr.value ) + os << i; + return os; + } }; // The ERROR_TRACE macro is designed for use in functions that detect or forward errors @@ -58,71 +58,71 @@ int const failure_percent = 25; leaf::result f1() { - ERROR_TRACE; - if( (std::rand()%100) > failure_percent ) - return { }; - else - return leaf::new_error(); + ERROR_TRACE; + if( (std::rand()%100) > failure_percent ) + return { }; + else + return leaf::new_error(); } leaf::result f2() { - ERROR_TRACE; - if( (std::rand()%100) > failure_percent ) - return f1(); - else - return leaf::new_error(); + ERROR_TRACE; + if( (std::rand()%100) > failure_percent ) + return f1(); + else + return leaf::new_error(); } leaf::result f3() { - ERROR_TRACE; - if( (std::rand()%100) > failure_percent ) - return f2(); - else - return leaf::new_error(); + ERROR_TRACE; + if( (std::rand()%100) > failure_percent ) + return f2(); + else + return leaf::new_error(); } leaf::result f4() { - ERROR_TRACE; - if( (std::rand()%100) > failure_percent ) - return f3(); - else - return leaf::new_error(); + ERROR_TRACE; + if( (std::rand()%100) > failure_percent ) + return f3(); + else + return leaf::new_error(); } leaf::result f5() { - ERROR_TRACE; - if( (std::rand()%100) > failure_percent ) - return f4(); - else - return leaf::new_error(); + ERROR_TRACE; + if( (std::rand()%100) > failure_percent ) + return f4(); + else + return leaf::new_error(); } int main() { - for( int i=0; i!=10; ++i ) - leaf::try_handle_all( - [&]() -> leaf::result - { - std::cout << "Run # " << i << ": "; - BOOST_LEAF_CHECK(f5()); - std::cout << "Success!" << std::endl; - return { }; - }, + for( int i=0; i!=10; ++i ) + leaf::try_handle_all( + [&]() -> leaf::result + { + std::cout << "Run # " << i << ": "; + BOOST_LEAF_CHECK(f5()); + std::cout << "Success!" << std::endl; + return { }; + }, #if ENABLE_ERROR_TRACE // This single #if enables or disables the capturing of the error trace. - []( e_error_trace const & tr ) - { - std::cerr << "Error! Trace:" << std::endl << tr; - }, + []( e_error_trace const & tr ) + { + std::cerr << "Error! Trace:" << std::endl << tr; + }, #endif - [] - { - std::cerr << "Error!" << std::endl; - } ); - return 0; + [] + { + std::cerr << "Error!" << std::endl; + } ); + return 0; } //////////////////////////////////////// @@ -131,17 +131,17 @@ int main() namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/exception_to_result.cpp b/examples/exception_to_result.cpp index 88ecea3..d565a44 100644 --- a/examples/exception_to_result.cpp +++ b/examples/exception_to_result.cpp @@ -24,86 +24,86 @@ class error_c: public virtual error_base { }; // Lower-level library function which throws exceptions. int compute_answer_throws() { - switch( rand()%4 ) - { - default: return 42; - case 1: throw error_a(); - case 2: throw error_b(); - case 3: throw error_c(); - } + switch( rand()%4 ) + { + default: return 42; + case 1: throw error_a(); + case 2: throw error_b(); + case 3: throw error_c(); + } } // Call compute_answer_throws, switch to result for error handling. leaf::result compute_answer() noexcept { - // Convert exceptions of types error_a and error_b to be communicated by leaf::result. - // Any other exception will be communicated as a std::exception_ptr. - return leaf::exception_to_result( - [] - { - return compute_answer_throws(); - } ); + // Convert exceptions of types error_a and error_b to be communicated by leaf::result. + // Any other exception will be communicated as a std::exception_ptr. + return leaf::exception_to_result( + [] + { + return compute_answer_throws(); + } ); } // Print the answer if the call to compute_answer is successful. leaf::result print_answer() noexcept { - BOOST_LEAF_AUTO( answer, compute_answer()); - std::cout << "Answer: " << answer << std::endl; - return { }; + BOOST_LEAF_AUTO( answer, compute_answer()); + std::cout << "Answer: " << answer << std::endl; + return { }; } int main() { - // Exercise print_answer a few times and handle errors. Note that the exception objects - // that compute_answer_throws throws are not handled as exceptions, but as regular - // LEAF error error objects... - for( int i=0; i!=42; ++i ) - { - leaf::try_handle_all( - []() -> leaf::result - { - BOOST_LEAF_CHECK(print_answer()); - return { }; - }, + // Exercise print_answer a few times and handle errors. Note that the exception objects + // that compute_answer_throws throws are not handled as exceptions, but as regular + // LEAF error error objects... + for( int i=0; i!=42; ++i ) + { + leaf::try_handle_all( + []() -> leaf::result + { + BOOST_LEAF_CHECK(print_answer()); + return { }; + }, - []( error_a const & e ) - { - std::cerr << "Error A!" << std::endl; - }, + []( error_a const & e ) + { + std::cerr << "Error A!" << std::endl; + }, - []( error_b const & e ) - { - std::cerr << "Error B!" << std::endl; - }, + []( error_b const & e ) + { + std::cerr << "Error B!" << std::endl; + }, - //...except for error_c errors, which (for demonstration) are captured as exceptions - // into std::exception_ptr as "unknown" exceptions. Presumably this should not - // happen, therefore at this point we treat this situation as a logic error: we print - // diagnostic information and bail out. - []( std::exception_ptr const * ep ) - { - std::cerr << "Got unknown error!" << std::endl; + //...except for error_c errors, which (for demonstration) are captured as exceptions + // into std::exception_ptr as "unknown" exceptions. Presumably this should not + // happen, therefore at this point we treat this situation as a logic error: we print + // diagnostic information and bail out. + []( std::exception_ptr const * ep ) + { + std::cerr << "Got unknown error!" << std::endl; - // Above, why do we take ep as a pointer? Because handle_all requires that the last - // handler matches any error and, taken as a pointer, if there isn't a std::exception_ptr - // associated with the error, the handler will still be matched (with 0 passed for ep). - // Had we taken it by value or by const &, the program would not have compiled. - if( ep ) - leaf::try_catch( - [&] - { - std::rethrow_exception(*ep); - }, - []( leaf::error_info const & unmatched ) - { - std::cerr << unmatched; - } ); - } ); - } + // Above, why do we take ep as a pointer? Because handle_all requires that the last + // handler matches any error and, taken as a pointer, if there isn't a std::exception_ptr + // associated with the error, the handler will still be matched (with 0 passed for ep). + // Had we taken it by value or by const &, the program would not have compiled. + if( ep ) + leaf::try_catch( + [&] + { + std::rethrow_exception(*ep); + }, + []( leaf::error_info const & unmatched ) + { + std::cerr << unmatched; + } ); + } ); + } - return 0; + return 0; } diff --git a/examples/lua_callback_eh.cpp b/examples/lua_callback_eh.cpp index 4e23353..b4cd607 100644 --- a/examples/lua_callback_eh.cpp +++ b/examples/lua_callback_eh.cpp @@ -7,8 +7,8 @@ // C-callback that happens to be C++-exception safe. extern "C" { - #include "lua.h" - #include "lauxlib.h" + #include "lua.h" + #include "lauxlib.h" } #include #include @@ -20,8 +20,8 @@ namespace leaf = boost::leaf; enum do_work_error_code { - ec1=1, - ec2 + ec1=1, + ec2 }; struct e_lua_pcall_error { int value; }; @@ -34,37 +34,37 @@ struct e_lua_error_message { std::string value; }; // pop back into the C++ code which called it (see call_lua below). int do_work( lua_State * L ) { - bool success = rand()%2; // "Sometimes" do_work fails. - if( success ) - { - lua_pushnumber(L, 42); // Success, push the result on the Lua stack, return to Lua. - return 1; - } - else - { - throw leaf::exception(ec1); - } + bool success = rand()%2; // "Sometimes" do_work fails. + if( success ) + { + lua_pushnumber(L, 42); // Success, push the result on the Lua stack, return to Lua. + return 1; + } + else + { + throw leaf::exception(ec1); + } } std::shared_ptr init_lua_state() { - // Create a new lua_State, we'll use std::shared_ptr for automatic cleanup. - std::shared_ptr L(lua_open(), &lua_close); + // Create a new lua_State, we'll use std::shared_ptr for automatic cleanup. + std::shared_ptr L(lua_open(), &lua_close); - // Register the do_work function (above) as a C callback, under the global - // Lua name "do_work". With this, calls from Lua programs to do_work - // will land in the do_work C function we've registered. - lua_register( &*L, "do_work", &do_work ); + // Register the do_work function (above) as a C callback, under the global + // Lua name "do_work". With this, calls from Lua programs to do_work + // will land in the do_work C function we've registered. + lua_register( &*L, "do_work", &do_work ); - // Pass some Lua code as a C string literal to Lua. This creates a global Lua - // function called "call_do_work", which we will later ask Lua to execute. - luaL_dostring( &*L, "\ + // Pass some Lua code as a C string literal to Lua. This creates a global Lua + // function called "call_do_work", which we will later ask Lua to execute. + luaL_dostring( &*L, "\ \n function call_do_work()\ \n return do_work()\ \n end" ); - return L; + return L; } @@ -76,60 +76,60 @@ std::shared_ptr init_lua_state() // If it fails, we'll communicate that failure to our caller. int call_lua( lua_State * L ) { - // Ask the Lua interpreter to call the global Lua function call_do_work. - lua_getfield( L, LUA_GLOBALSINDEX, "call_do_work" ); - if( int err = lua_pcall(L, 0, 1, 0) ) // Ask Lua to call the global function call_do_work. - { - auto load = leaf::on_error(e_lua_error_message{lua_tostring(L, 1)}); - lua_pop(L,1); + // Ask the Lua interpreter to call the global Lua function call_do_work. + lua_getfield( L, LUA_GLOBALSINDEX, "call_do_work" ); + if( int err = lua_pcall(L, 0, 1, 0) ) // Ask Lua to call the global function call_do_work. + { + auto load = leaf::on_error(e_lua_error_message{lua_tostring(L, 1)}); + lua_pop(L,1); - // We got a Lua error that is definitely not the error we're throwing in do_work. - // (if it did throw an exception, we won't be here). - // Throw a new exception to indicate that lua_pcall returned an error. - throw leaf::exception(e_lua_pcall_error{err}); - } - else - { - // Success! Just return the int answer. - int answer=lua_tonumber(L, -1); - lua_pop(L,1); - return answer; - } + // We got a Lua error that is definitely not the error we're throwing in do_work. + // (if it did throw an exception, we won't be here). + // Throw a new exception to indicate that lua_pcall returned an error. + throw leaf::exception(e_lua_pcall_error{err}); + } + else + { + // Success! Just return the int answer. + int answer=lua_tonumber(L, -1); + lua_pop(L,1); + return answer; + } } int main() { - std::shared_ptr L=init_lua_state(); + std::shared_ptr L=init_lua_state(); - for( int i=0; i!=10; ++i ) - { - leaf::try_catch( + for( int i=0; i!=10; ++i ) + { + leaf::try_catch( - [&] - { - int answer = call_lua(&*L); - std::cout << "do_work succeeded, answer=" << answer << '\n'; + [&] + { + int answer = call_lua(&*L); + std::cout << "do_work succeeded, answer=" << answer << '\n'; - }, + }, - []( do_work_error_code e ) - { - std::cout << "Got do_work_error_code = " << e << "!\n"; - }, + []( do_work_error_code e ) + { + std::cout << "Got do_work_error_code = " << e << "!\n"; + }, - []( e_lua_pcall_error const & err, e_lua_error_message const & msg ) - { - std::cout << "Got e_lua_pcall_error, Lua error code = " << err.value << ", " << msg.value << "\n"; - }, + []( e_lua_pcall_error const & err, e_lua_error_message const & msg ) + { + std::cout << "Got e_lua_pcall_error, Lua error code = " << err.value << ", " << msg.value << "\n"; + }, - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - } ); - } + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + } ); + } - return 0; + return 0; } diff --git a/examples/lua_callback_result.cpp b/examples/lua_callback_result.cpp index 6c5eb79..0de1c7e 100644 --- a/examples/lua_callback_result.cpp +++ b/examples/lua_callback_result.cpp @@ -7,8 +7,8 @@ // C-callback, converting them to leaf::result as soon as controlreaches C++. extern "C" { - #include "lua.h" - #include "lauxlib.h" + #include "lua.h" + #include "lauxlib.h" } #include #include @@ -20,8 +20,8 @@ namespace leaf = boost::leaf; enum do_work_error_code { - ec1=1, - ec2 + ec1=1, + ec2 }; struct e_lua_pcall_error { int value; }; @@ -34,37 +34,37 @@ struct e_lua_error_message { std::string value; }; // pop back into the C++ code which called it (see call_lua below). int do_work( lua_State * L ) { - bool success = rand()%2; // "Sometimes" do_work fails. - if( success ) - { - lua_pushnumber(L, 42); // Success, push the result on the Lua stack, return to Lua. - return 1; - } - else - { - return leaf::new_error(ec1), luaL_error(L,"do_work_error"); // luaL_error does not return (longjmp). - } + bool success = rand()%2; // "Sometimes" do_work fails. + if( success ) + { + lua_pushnumber(L, 42); // Success, push the result on the Lua stack, return to Lua. + return 1; + } + else + { + return leaf::new_error(ec1), luaL_error(L,"do_work_error"); // luaL_error does not return (longjmp). + } } std::shared_ptr init_lua_state() { - // Create a new lua_State, we'll use std::shared_ptr for automatic cleanup. - std::shared_ptr L(lua_open(), &lua_close); + // Create a new lua_State, we'll use std::shared_ptr for automatic cleanup. + std::shared_ptr L(lua_open(), &lua_close); - // Register the do_work function (above) as a C callback, under the global - // Lua name "do_work". With this, calls from Lua programs to do_work - // will land in the do_work C function we've registered. - lua_register( &*L, "do_work", &do_work ); + // Register the do_work function (above) as a C callback, under the global + // Lua name "do_work". With this, calls from Lua programs to do_work + // will land in the do_work C function we've registered. + lua_register( &*L, "do_work", &do_work ); - // Pass some Lua code as a C string literal to Lua. This creates a global Lua - // function called "call_do_work", which we will later ask Lua to execute. - luaL_dostring( &*L, "\ + // Pass some Lua code as a C string literal to Lua. This creates a global Lua + // function called "call_do_work", which we will later ask Lua to execute. + luaL_dostring( &*L, "\ \n function call_do_work()\ \n return do_work()\ \n end" ); - return L; + return L; } @@ -76,81 +76,81 @@ std::shared_ptr init_lua_state() // If it fails, we'll communicate that failure to our caller. leaf::result call_lua( lua_State * L ) { - leaf::error_monitor cur_err; + leaf::error_monitor cur_err; - // Ask the Lua interpreter to call the global Lua function call_do_work. - lua_getfield( L, LUA_GLOBALSINDEX, "call_do_work" ); - if( int err = lua_pcall(L, 0, 1, 0) ) // Ask Lua to call the global function call_do_work. - { - auto load = leaf::on_error(e_lua_error_message{lua_tostring(L, 1)}); - lua_pop(L,1); + // Ask the Lua interpreter to call the global Lua function call_do_work. + lua_getfield( L, LUA_GLOBALSINDEX, "call_do_work" ); + if( int err = lua_pcall(L, 0, 1, 0) ) // Ask Lua to call the global function call_do_work. + { + auto load = leaf::on_error(e_lua_error_message{lua_tostring(L, 1)}); + lua_pop(L,1); - // We got a Lua error which may be the error we're reporting from do_work, or some other error. - // If it is another error, cur_err.assigned_error_id() will return a new leaf::error_id, - // otherwise we'll be working with the original value returned by leaf::new_error in do_work. - return cur_err.assigned_error_id().load(e_lua_pcall_error{err}); - } - else - { - // Success! Just return the int answer. - int answer=lua_tonumber(L, -1); - lua_pop(L,1); - return answer; - } + // We got a Lua error which may be the error we're reporting from do_work, or some other error. + // If it is another error, cur_err.assigned_error_id() will return a new leaf::error_id, + // otherwise we'll be working with the original value returned by leaf::new_error in do_work. + return cur_err.assigned_error_id().load(e_lua_pcall_error{err}); + } + else + { + // Success! Just return the int answer. + int answer=lua_tonumber(L, -1); + lua_pop(L,1); + return answer; + } } int main() { - std::shared_ptr L=init_lua_state(); + std::shared_ptr L=init_lua_state(); - for( int i=0; i!=10; ++i ) - { - leaf::try_handle_all( + for( int i=0; i!=10; ++i ) + { + leaf::try_handle_all( - [&]() -> leaf::result - { - BOOST_LEAF_AUTO(answer, call_lua(&*L)); - std::cout << "do_work succeeded, answer=" << answer << '\n'; - return { }; - }, + [&]() -> leaf::result + { + BOOST_LEAF_AUTO(answer, call_lua(&*L)); + std::cout << "do_work succeeded, answer=" << answer << '\n'; + return { }; + }, - []( do_work_error_code e ) - { - std::cout << "Got do_work_error_code = " << e << "!\n"; - }, + []( do_work_error_code e ) + { + std::cout << "Got do_work_error_code = " << e << "!\n"; + }, - []( e_lua_pcall_error const & err, e_lua_error_message const & msg ) - { - std::cout << "Got e_lua_pcall_error, Lua error code = " << err.value << ", " << msg.value << "\n"; - }, + []( e_lua_pcall_error const & err, e_lua_error_message const & msg ) + { + std::cout << "Got e_lua_pcall_error, Lua error code = " << err.value << ", " << msg.value << "\n"; + }, - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - } ); - } + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + } ); + } - return 0; + return 0; } #ifdef BOOST_LEAF_NO_EXCEPTIONS namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/print_file/print_file_eh.cpp b/examples/print_file/print_file_eh.cpp index b259e3e..9665c31 100644 --- a/examples/print_file/print_file_eh.cpp +++ b/examples/print_file/print_file_eh.cpp @@ -50,92 +50,92 @@ void file_read( FILE & f, void * buf, int size ); // The main function, which handles all errors. int main( int argc, char const * argv[] ) { - return leaf::try_catch( + return leaf::try_catch( - [&] - { - char const * file_name = parse_command_line(argc,argv); + [&] + { + char const * file_name = parse_command_line(argc,argv); - auto load = leaf::on_error( leaf::e_file_name{file_name} ); + auto load = leaf::on_error( leaf::e_file_name{file_name} ); - std::shared_ptr f = file_open(file_name); + std::shared_ptr f = file_open(file_name); - int s = file_size(*f); + int s = file_size(*f); - std::string buffer(1 + s, '\0'); - file_read(*f, &buffer[0], buffer.size()-1); + std::string buffer(1 + s, '\0'); + file_read(*f, &buffer[0], buffer.size()-1); - std::cout << buffer; - std::cout.flush(); - if( std::cout.fail() ) - throw leaf::exception(output_error{}, leaf::e_errno{errno}); + std::cout << buffer; + std::cout.flush(); + if( std::cout.fail() ) + throw leaf::exception(output_error{}, leaf::e_errno{errno}); - return 0; - }, + return 0; + }, - // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches - // the available error objects. + // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches + // the available error objects. - // This handler will be called if the error includes: - // - a caught exception of type open_error, and - // - an object of type leaf::e_errno that has .value equal to ENOENT, and - // - an object of type leaf::e_file_name. - []( open_error &, leaf::match_value, leaf::e_file_name const & fn ) - { - std::cerr << "File not found: " << fn.value << std::endl; - return 1; - }, + // This handler will be called if the error includes: + // - a caught exception of type open_error, and + // - an object of type leaf::e_errno that has .value equal to ENOENT, and + // - an object of type leaf::e_file_name. + []( open_error &, leaf::match_value, leaf::e_file_name const & fn ) + { + std::cerr << "File not found: " << fn.value << std::endl; + return 1; + }, - // This handler will be called if the error includes: - // - a caught exception of type open_error, and - // - an object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( open_error &, leaf::e_errno const & errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; - return 2; - }, + // This handler will be called if the error includes: + // - a caught exception of type open_error, and + // - an object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( open_error &, leaf::e_errno const & errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; + return 2; + }, - // This handler will be called if the error includes: - // - a caught exception of type input_error, and - // - an optional object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( input_error &, leaf::e_errno const * errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to access " << fn.value; - if( errn ) - std::cerr << ", errno=" << *errn; - std::cerr << std::endl; - return 3; - }, + // This handler will be called if the error includes: + // - a caught exception of type input_error, and + // - an optional object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( input_error &, leaf::e_errno const * errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to access " << fn.value; + if( errn ) + std::cerr << ", errno=" << *errn; + std::cerr << std::endl; + return 3; + }, - // This handler will be called if the error includes: - // - a caught exception of type std::ostream::failure, and - // - an object of type leaf::e_errno (regardless of its .value), - []( output_error &, leaf::e_errno const & errn ) - { - std::cerr << "Output error, errno=" << errn << std::endl; - return 4; - }, + // This handler will be called if the error includes: + // - a caught exception of type std::ostream::failure, and + // - an object of type leaf::e_errno (regardless of its .value), + []( output_error &, leaf::e_errno const & errn ) + { + std::cerr << "Output error, errno=" << errn << std::endl; + return 4; + }, - // This handler will be called if we've got a bad_command_line - []( bad_command_line & ) - { - std::cout << "Bad command line argument" << std::endl; - return 5; - }, + // This handler will be called if we've got a bad_command_line + []( bad_command_line & ) + { + std::cout << "Bad command line argument" << std::endl; + return 5; + }, - // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it - // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will - // never be called. - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - return 6; - } ); + // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it + // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will + // never be called. + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + return 6; + } ); } @@ -145,50 +145,50 @@ int main( int argc, char const * argv[] ) // Parse the command line, return the file name. char const * parse_command_line( int argc, char const * argv[] ) { - if( argc==2 ) - return argv[1]; - else - throw leaf::exception(bad_command_line{}); + if( argc==2 ) + return argv[1]; + else + throw leaf::exception(bad_command_line{}); } // Open a file for reading. std::shared_ptr file_open( char const * file_name ) { - if( FILE * f = fopen(file_name, "rb") ) - return std::shared_ptr(f, &fclose); - else - throw leaf::exception(open_error{}, leaf::e_errno{errno}); + if( FILE * f = fopen(file_name, "rb") ) + return std::shared_ptr(f, &fclose); + else + throw leaf::exception(open_error{}, leaf::e_errno{errno}); } // Return the size of the file. int file_size( FILE & f ) { - auto load = leaf::on_error([] { return leaf::e_errno{errno}; }); + auto load = leaf::on_error([] { return leaf::e_errno{errno}; }); - if( fseek(&f, 0, SEEK_END) ) - throw leaf::exception(size_error{}); + if( fseek(&f, 0, SEEK_END) ) + throw leaf::exception(size_error{}); - int s = ftell(&f); - if( s==-1L ) - throw leaf::exception(size_error{}); + int s = ftell(&f); + if( s==-1L ) + throw leaf::exception(size_error{}); - if( fseek(&f,0,SEEK_SET) ) - throw leaf::exception(size_error{}); + if( fseek(&f,0,SEEK_SET) ) + throw leaf::exception(size_error{}); - return s; + return s; } // Read size bytes from f into buf. void file_read( FILE & f, void * buf, int size ) { - int n = fread(buf, 1, size, &f); + int n = fread(buf, 1, size, &f); - if( ferror(&f) ) - throw leaf::exception(read_error{}, leaf::e_errno{errno}); + if( ferror(&f) ) + throw leaf::exception(read_error{}, leaf::e_errno{errno}); - if( n!=size ) - throw leaf::exception(eof_error{}); + if( n!=size ) + throw leaf::exception(eof_error{}); } diff --git a/examples/print_file/print_file_eh_error_tags.cpp b/examples/print_file/print_file_eh_error_tags.cpp index a00517c..648796e 100644 --- a/examples/print_file/print_file_eh_error_tags.cpp +++ b/examples/print_file/print_file_eh_error_tags.cpp @@ -50,92 +50,92 @@ void file_read( FILE & f, void * buf, int size ); // The main function, which handles all errors. int main( int argc, char const * argv[] ) { - return leaf::try_catch( + return leaf::try_catch( - [&] - { - char const * file_name = parse_command_line(argc,argv); + [&] + { + char const * file_name = parse_command_line(argc,argv); - auto load = leaf::on_error( leaf::e_file_name{file_name} ); + auto load = leaf::on_error( leaf::e_file_name{file_name} ); - std::shared_ptr f = file_open(file_name); + std::shared_ptr f = file_open(file_name); - int s = file_size(*f); + int s = file_size(*f); - std::string buffer(1 + s, '\0'); - file_read(*f, &buffer[0], buffer.size()-1); + std::string buffer(1 + s, '\0'); + file_read(*f, &buffer[0], buffer.size()-1); - std::cout << buffer; - std::cout.flush(); - if( std::cout.fail() ) - throw leaf::exception(output_error{}, leaf::e_errno{errno}); + std::cout << buffer; + std::cout.flush(); + if( std::cout.fail() ) + throw leaf::exception(output_error{}, leaf::e_errno{errno}); - return 0; - }, + return 0; + }, - // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches - // the available error objects. + // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches + // the available error objects. - // This handler will be called if the error includes: - // - an object of type open_error, and - // - an object of type leaf::e_errno that has .value equal to ENOENT, and - // - an object of type leaf::e_file_name. - []( open_error &, leaf::match_value, leaf::e_file_name const & fn ) - { - std::cerr << "File not found: " << fn.value << std::endl; - return 1; - }, + // This handler will be called if the error includes: + // - an object of type open_error, and + // - an object of type leaf::e_errno that has .value equal to ENOENT, and + // - an object of type leaf::e_file_name. + []( open_error &, leaf::match_value, leaf::e_file_name const & fn ) + { + std::cerr << "File not found: " << fn.value << std::endl; + return 1; + }, - // This handler will be called if the error includes: - // - an object of type open_error, and - // - an object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( open_error &, leaf::e_errno const & errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; - return 2; - }, + // This handler will be called if the error includes: + // - an object of type open_error, and + // - an object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( open_error &, leaf::e_errno const & errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; + return 2; + }, - // This handler will be called if the error includes: - // - an object of type input_error, and - // - an optional object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( input_error &, leaf::e_errno const * errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to access " << fn.value; - if( errn ) - std::cerr << ", errno=" << *errn; - std::cerr << std::endl; - return 3; - }, + // This handler will be called if the error includes: + // - an object of type input_error, and + // - an optional object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( input_error &, leaf::e_errno const * errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to access " << fn.value; + if( errn ) + std::cerr << ", errno=" << *errn; + std::cerr << std::endl; + return 3; + }, - // This handler will be called if the error includes: - // - an object of type output_error, and - // - an object of type leaf::e_errno (regardless of its .value), - []( output_error &, leaf::e_errno const & errn ) - { - std::cerr << "Output error, errno=" << errn << std::endl; - return 4; - }, + // This handler will be called if the error includes: + // - an object of type output_error, and + // - an object of type leaf::e_errno (regardless of its .value), + []( output_error &, leaf::e_errno const & errn ) + { + std::cerr << "Output error, errno=" << errn << std::endl; + return 4; + }, - // This handler will be called if we've got a bad_command_line - []( bad_command_line & ) - { - std::cout << "Bad command line argument" << std::endl; - return 5; - }, + // This handler will be called if we've got a bad_command_line + []( bad_command_line & ) + { + std::cout << "Bad command line argument" << std::endl; + return 5; + }, - // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it - // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will - // never be called. - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - return 6; - } ); + // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it + // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will + // never be called. + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + return 6; + } ); } @@ -145,54 +145,54 @@ int main( int argc, char const * argv[] ) // Parse the command line, return the file name. char const * parse_command_line( int argc, char const * argv[] ) { - if( argc==2 ) - return argv[1]; - else - throw leaf::exception(bad_command_line{}); + if( argc==2 ) + return argv[1]; + else + throw leaf::exception(bad_command_line{}); } // Open a file for reading. std::shared_ptr file_open( char const * file_name ) { - auto load = leaf::on_error(input_error{}); + auto load = leaf::on_error(input_error{}); - if( FILE * f = fopen(file_name, "rb") ) - return std::shared_ptr(f, &fclose); - else - throw leaf::exception(open_error{}, leaf::e_errno{errno}); + if( FILE * f = fopen(file_name, "rb") ) + return std::shared_ptr(f, &fclose); + else + throw leaf::exception(open_error{}, leaf::e_errno{errno}); } // Return the size of the file. int file_size( FILE & f ) { - auto load = leaf::on_error(input_error{}, size_error{}, []{ return leaf::e_errno{errno}; }); + auto load = leaf::on_error(input_error{}, size_error{}, []{ return leaf::e_errno{errno}; }); - if( fseek(&f, 0, SEEK_END) ) - throw leaf::exception(); + if( fseek(&f, 0, SEEK_END) ) + throw leaf::exception(); - int s = ftell(&f); - if( s==-1L ) - throw leaf::exception(); + int s = ftell(&f); + if( s==-1L ) + throw leaf::exception(); - if( fseek(&f,0,SEEK_SET) ) - throw leaf::exception(); + if( fseek(&f,0,SEEK_SET) ) + throw leaf::exception(); - return s; + return s; } // Read size bytes from f into buf. void file_read( FILE & f, void * buf, int size ) { - auto load = leaf::on_error(input_error{}); + auto load = leaf::on_error(input_error{}); - int n = fread(buf, 1, size, &f); + int n = fread(buf, 1, size, &f); - if( ferror(&f) ) - throw leaf::exception(read_error{}, leaf::e_errno{errno}); + if( ferror(&f) ) + throw leaf::exception(read_error{}, leaf::e_errno{errno}); - if( n!=size ) - throw leaf::exception(eof_error{}); + if( n!=size ) + throw leaf::exception(eof_error{}); } diff --git a/examples/print_file/print_file_outcome_result.cpp b/examples/print_file/print_file_outcome_result.cpp index 0277c2d..c474b84 100644 --- a/examples/print_file/print_file_outcome_result.cpp +++ b/examples/print_file/print_file_outcome_result.cpp @@ -25,12 +25,12 @@ namespace leaf = boost::leaf; // First, we need an enum to define our error codes: enum error_code { - bad_command_line = 1, - open_error, - read_error, - size_error, - eof_error, - output_error + bad_command_line = 1, + open_error, + read_error, + size_error, + eof_error, + output_error }; @@ -39,7 +39,7 @@ using result = outcome::std_result; // To enable LEAF to work with outcome::result, we need to specialize the is_result_type template: namespace boost { namespace leaf { - template struct is_result_type>: std::true_type { }; + template struct is_result_type>: std::true_type { }; } } @@ -62,92 +62,92 @@ result file_read( FILE & f, void * buf, int size ); // The main function, which handles all errors. int main( int argc, char const * argv[] ) { - return leaf::try_handle_all( + return leaf::try_handle_all( - [&]() -> result - { - BOOST_LEAF_AUTO(file_name, parse_command_line(argc,argv)); + [&]() -> result + { + BOOST_LEAF_AUTO(file_name, parse_command_line(argc,argv)); - auto load = leaf::on_error( leaf::e_file_name{file_name} ); + auto load = leaf::on_error( leaf::e_file_name{file_name} ); - BOOST_LEAF_AUTO(f, file_open(file_name)); + BOOST_LEAF_AUTO(f, file_open(file_name)); - BOOST_LEAF_AUTO(s, file_size(*f)); + BOOST_LEAF_AUTO(s, file_size(*f)); - std::string buffer(1 + s, '\0'); - BOOST_LEAF_CHECK(file_read(*f, &buffer[0], buffer.size()-1)); + std::string buffer(1 + s, '\0'); + BOOST_LEAF_CHECK(file_read(*f, &buffer[0], buffer.size()-1)); - std::cout << buffer; - std::cout.flush(); - if( std::cout.fail() ) - return leaf::new_error(output_error, leaf::e_errno{errno}).to_error_code(); + std::cout << buffer; + std::cout.flush(); + if( std::cout.fail() ) + return leaf::new_error(output_error, leaf::e_errno{errno}).to_error_code(); - return 0; - }, + return 0; + }, - // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches - // the available error objects. + // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches + // the available error objects. - // This handler will be called if the error includes: - // - an object of type error_code equal to open_error, and - // - an object of type leaf::e_errno that has .value equal to ENOENT, and - // - an object of type leaf::e_file_name. - []( leaf::match, leaf::match_value, leaf::e_file_name const & fn ) - { - std::cerr << "File not found: " << fn.value << std::endl; - return 1; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to open_error, and + // - an object of type leaf::e_errno that has .value equal to ENOENT, and + // - an object of type leaf::e_file_name. + []( leaf::match, leaf::match_value, leaf::e_file_name const & fn ) + { + std::cerr << "File not found: " << fn.value << std::endl; + return 1; + }, - // This handler will be called if the error includes: - // - an object of type error_code equal to open_error, and - // - an object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( leaf::match, leaf::e_errno const & errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; - return 2; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to open_error, and + // - an object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( leaf::match, leaf::e_errno const & errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; + return 2; + }, - // This handler will be called if the error includes: - // - an object of type error_code equal to any of size_error, read_error, eof_error, and - // - an optional object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( leaf::match, leaf::e_errno const * errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to access " << fn.value; - if( errn ) - std::cerr << ", errno=" << *errn; - std::cerr << std::endl; - return 3; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to any of size_error, read_error, eof_error, and + // - an optional object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( leaf::match, leaf::e_errno const * errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to access " << fn.value; + if( errn ) + std::cerr << ", errno=" << *errn; + std::cerr << std::endl; + return 3; + }, - // This handler will be called if the error includes: - // - an object of type error_code equal to output_error, and - // - an object of type leaf::e_errno (regardless of its .value), - []( leaf::match, leaf::e_errno const & errn ) - { - std::cerr << "Output error, errno=" << errn << std::endl; - return 4; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to output_error, and + // - an object of type leaf::e_errno (regardless of its .value), + []( leaf::match, leaf::e_errno const & errn ) + { + std::cerr << "Output error, errno=" << errn << std::endl; + return 4; + }, - // This handler will be called if we've got a bad_command_line - []( leaf::match ) - { - std::cout << "Bad command line argument" << std::endl; - return 5; - }, + // This handler will be called if we've got a bad_command_line + []( leaf::match ) + { + std::cout << "Bad command line argument" << std::endl; + return 5; + }, - // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it - // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will - // never be called. - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - return 6; - } ); + // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it + // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will + // never be called. + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + return 6; + } ); } @@ -157,54 +157,54 @@ int main( int argc, char const * argv[] ) // Parse the command line, return the file name. result parse_command_line( int argc, char const * argv[] ) { - if( argc==2 ) - return argv[1]; - else - return leaf::new_error(bad_command_line).to_error_code(); + if( argc==2 ) + return argv[1]; + else + return leaf::new_error(bad_command_line).to_error_code(); } // Open a file for reading. result> file_open( char const * file_name ) { - if( FILE * f = fopen(file_name, "rb") ) - return std::shared_ptr(f, &fclose); - else - return leaf::new_error(open_error, leaf::e_errno{errno}).to_error_code(); + if( FILE * f = fopen(file_name, "rb") ) + return std::shared_ptr(f, &fclose); + else + return leaf::new_error(open_error, leaf::e_errno{errno}).to_error_code(); } // Return the size of the file. result file_size( FILE & f ) { - auto load = leaf::on_error([] { return leaf::e_errno{errno}; }); + auto load = leaf::on_error([] { return leaf::e_errno{errno}; }); - if( fseek(&f, 0, SEEK_END) ) - return leaf::new_error(size_error).to_error_code(); + if( fseek(&f, 0, SEEK_END) ) + return leaf::new_error(size_error).to_error_code(); - int s = ftell(&f); - if( s==-1L ) - return leaf::new_error(size_error).to_error_code(); + int s = ftell(&f); + if( s==-1L ) + return leaf::new_error(size_error).to_error_code(); - if( fseek(&f,0,SEEK_SET) ) - return leaf::new_error(size_error).to_error_code(); + if( fseek(&f,0,SEEK_SET) ) + return leaf::new_error(size_error).to_error_code(); - return s; + return s; } // Read size bytes from f into buf. result file_read( FILE & f, void * buf, int size ) { - int n = fread(buf, 1, size, &f); + int n = fread(buf, 1, size, &f); - if( ferror(&f) ) - return leaf::new_error(read_error, leaf::e_errno{errno}).to_error_code(); + if( ferror(&f) ) + return leaf::new_error(read_error, leaf::e_errno{errno}).to_error_code(); - if( n!=size ) - return leaf::new_error(eof_error).to_error_code(); + if( n!=size ) + return leaf::new_error(eof_error).to_error_code(); - return outcome::success(); + return outcome::success(); } //////////////////////////////////////// @@ -213,17 +213,17 @@ result file_read( FILE & f, void * buf, int size ) namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/print_file/print_file_result.cpp b/examples/print_file/print_file_result.cpp index 25f17b7..50c5359 100644 --- a/examples/print_file/print_file_result.cpp +++ b/examples/print_file/print_file_result.cpp @@ -24,12 +24,12 @@ namespace leaf = boost::leaf; // First, we need an enum to define our error codes: enum error_code { - bad_command_line = 1, - open_error, - read_error, - size_error, - eof_error, - output_error + bad_command_line = 1, + open_error, + read_error, + size_error, + eof_error, + output_error }; @@ -56,92 +56,92 @@ result file_read( FILE & f, void * buf, int size ); // The main function, which handles all errors. int main( int argc, char const * argv[] ) { - return leaf::try_handle_all( + return leaf::try_handle_all( - [&]() -> result - { - BOOST_LEAF_AUTO(file_name, parse_command_line(argc,argv)); + [&]() -> result + { + BOOST_LEAF_AUTO(file_name, parse_command_line(argc,argv)); - auto load = leaf::on_error( leaf::e_file_name{file_name} ); + auto load = leaf::on_error( leaf::e_file_name{file_name} ); - BOOST_LEAF_AUTO(f, file_open(file_name)); + BOOST_LEAF_AUTO(f, file_open(file_name)); - BOOST_LEAF_AUTO(s, file_size(*f)); + BOOST_LEAF_AUTO(s, file_size(*f)); - std::string buffer(1 + s, '\0'); - BOOST_LEAF_CHECK(file_read(*f, &buffer[0], buffer.size()-1)); + std::string buffer(1 + s, '\0'); + BOOST_LEAF_CHECK(file_read(*f, &buffer[0], buffer.size()-1)); - std::cout << buffer; - std::cout.flush(); - if( std::cout.fail() ) - return leaf::new_error(output_error, leaf::e_errno{errno}); + std::cout << buffer; + std::cout.flush(); + if( std::cout.fail() ) + return leaf::new_error(output_error, leaf::e_errno{errno}); - return 0; - }, + return 0; + }, - // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches - // the available error objects. + // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches + // the available error objects. - // This handler will be called if the error includes: - // - an object of type error_code equal to open_error, and - // - an object of type leaf::e_errno that has .value equal to ENOENT, and - // - an object of type leaf::e_file_name. - []( leaf::match, leaf::match_value, leaf::e_file_name const & fn ) - { - std::cerr << "File not found: " << fn.value << std::endl; - return 1; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to open_error, and + // - an object of type leaf::e_errno that has .value equal to ENOENT, and + // - an object of type leaf::e_file_name. + []( leaf::match, leaf::match_value, leaf::e_file_name const & fn ) + { + std::cerr << "File not found: " << fn.value << std::endl; + return 1; + }, - // This handler will be called if the error includes: - // - an object of type error_code equal to open_error, and - // - an object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( leaf::match, leaf::e_errno const & errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; - return 2; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to open_error, and + // - an object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( leaf::match, leaf::e_errno const & errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; + return 2; + }, - // This handler will be called if the error includes: - // - an object of type error_code equal to any of size_error, read_error, eof_error, and - // - an optional object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( leaf::match, leaf::e_errno const * errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to access " << fn.value; - if( errn ) - std::cerr << ", errno=" << *errn; - std::cerr << std::endl; - return 3; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to any of size_error, read_error, eof_error, and + // - an optional object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( leaf::match, leaf::e_errno const * errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to access " << fn.value; + if( errn ) + std::cerr << ", errno=" << *errn; + std::cerr << std::endl; + return 3; + }, - // This handler will be called if the error includes: - // - an object of type error_code equal to output_error, and - // - an object of type leaf::e_errno (regardless of its .value), - []( leaf::match, leaf::e_errno const & errn ) - { - std::cerr << "Output error, errno=" << errn << std::endl; - return 4; - }, + // This handler will be called if the error includes: + // - an object of type error_code equal to output_error, and + // - an object of type leaf::e_errno (regardless of its .value), + []( leaf::match, leaf::e_errno const & errn ) + { + std::cerr << "Output error, errno=" << errn << std::endl; + return 4; + }, - // This handler will be called if we've got a bad_command_line - []( leaf::match ) - { - std::cout << "Bad command line argument" << std::endl; - return 5; - }, + // This handler will be called if we've got a bad_command_line + []( leaf::match ) + { + std::cout << "Bad command line argument" << std::endl; + return 5; + }, - // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it - // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will - // never be called. - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - return 6; - } ); + // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it + // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will + // never be called. + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + return 6; + } ); } @@ -151,54 +151,54 @@ int main( int argc, char const * argv[] ) // Parse the command line, return the file name. result parse_command_line( int argc, char const * argv[] ) { - if( argc==2 ) - return argv[1]; - else - return leaf::new_error(bad_command_line); + if( argc==2 ) + return argv[1]; + else + return leaf::new_error(bad_command_line); } // Open a file for reading. result> file_open( char const * file_name ) { - if( FILE * f = fopen(file_name, "rb") ) - return std::shared_ptr(f, &fclose); - else - return leaf::new_error(open_error, leaf::e_errno{errno}); + if( FILE * f = fopen(file_name, "rb") ) + return std::shared_ptr(f, &fclose); + else + return leaf::new_error(open_error, leaf::e_errno{errno}); } // Return the size of the file. result file_size( FILE & f ) { - auto load = leaf::on_error([] { return leaf::e_errno{errno}; }); + auto load = leaf::on_error([] { return leaf::e_errno{errno}; }); - if( fseek(&f, 0, SEEK_END) ) - return leaf::new_error(size_error); + if( fseek(&f, 0, SEEK_END) ) + return leaf::new_error(size_error); - int s = ftell(&f); - if( s==-1L ) - return leaf::new_error(size_error); + int s = ftell(&f); + if( s==-1L ) + return leaf::new_error(size_error); - if( fseek(&f,0,SEEK_SET) ) - return leaf::new_error(size_error); + if( fseek(&f,0,SEEK_SET) ) + return leaf::new_error(size_error); - return s; + return s; } // Read size bytes from f into buf. result file_read( FILE & f, void * buf, int size ) { - int n = fread(buf, 1, size, &f); + int n = fread(buf, 1, size, &f); - if( ferror(&f) ) - return leaf::new_error(read_error, leaf::e_errno{errno}); + if( ferror(&f) ) + return leaf::new_error(read_error, leaf::e_errno{errno}); - if( n!=size ) - return leaf::new_error(eof_error); + if( n!=size ) + return leaf::new_error(eof_error); - return { }; + return { }; } //////////////////////////////////////// @@ -207,17 +207,17 @@ result file_read( FILE & f, void * buf, int size ) namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/print_file/print_file_result_error_tags.cpp b/examples/print_file/print_file_result_error_tags.cpp index 7f1896a..5549a83 100644 --- a/examples/print_file/print_file_result_error_tags.cpp +++ b/examples/print_file/print_file_result_error_tags.cpp @@ -55,92 +55,92 @@ result file_read( FILE & f, void * buf, int size ); // The main function, which handles all errors. int main( int argc, char const * argv[] ) { - return leaf::try_handle_all( + return leaf::try_handle_all( - [&]() -> result - { - BOOST_LEAF_AUTO(file_name, parse_command_line(argc,argv)); + [&]() -> result + { + BOOST_LEAF_AUTO(file_name, parse_command_line(argc,argv)); - auto load = leaf::on_error( leaf::e_file_name{file_name} ); + auto load = leaf::on_error( leaf::e_file_name{file_name} ); - BOOST_LEAF_AUTO(f, file_open(file_name)); + BOOST_LEAF_AUTO(f, file_open(file_name)); - BOOST_LEAF_AUTO(s, file_size(*f)); + BOOST_LEAF_AUTO(s, file_size(*f)); - std::string buffer(1 + s, '\0'); - BOOST_LEAF_CHECK(file_read(*f, &buffer[0], buffer.size()-1)); + std::string buffer(1 + s, '\0'); + BOOST_LEAF_CHECK(file_read(*f, &buffer[0], buffer.size()-1)); - std::cout << buffer; - std::cout.flush(); - if( std::cout.fail() ) - return leaf::new_error(output_error{}, leaf::e_errno{errno}); + std::cout << buffer; + std::cout.flush(); + if( std::cout.fail() ) + return leaf::new_error(output_error{}, leaf::e_errno{errno}); - return 0; - }, + return 0; + }, - // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches - // the available error objects. + // Each of the lambdas below is an error handler. LEAF will consider them, in order, and call the first one that matches + // the available error objects. - // This handler will be called if the error includes: - // - an object of type open_error, and - // - an object of type leaf::e_errno that has .value equal to ENOENT, and - // - an object of type leaf::e_file_name. - []( open_error &, leaf::match_value, leaf::e_file_name const & fn ) - { - std::cerr << "File not found: " << fn.value << std::endl; - return 1; - }, + // This handler will be called if the error includes: + // - an object of type open_error, and + // - an object of type leaf::e_errno that has .value equal to ENOENT, and + // - an object of type leaf::e_file_name. + []( open_error &, leaf::match_value, leaf::e_file_name const & fn ) + { + std::cerr << "File not found: " << fn.value << std::endl; + return 1; + }, - // This handler will be called if the error includes: - // - an object of type open_error, and - // - an object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( open_error &, leaf::e_errno const & errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; - return 2; - }, + // This handler will be called if the error includes: + // - an object of type open_error, and + // - an object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( open_error &, leaf::e_errno const & errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to open " << fn.value << ", errno=" << errn << std::endl; + return 2; + }, - // This handler will be called if the error includes: - // - an object of type input_error, and - // - an optional object of type leaf::e_errno (regardless of its .value), and - // - an object of type leaf::e_file_name. - []( input_error &, leaf::e_errno const * errn, leaf::e_file_name const & fn ) - { - std::cerr << "Failed to access " << fn.value; - if( errn ) - std::cerr << ", errno=" << *errn; - std::cerr << std::endl; - return 3; - }, + // This handler will be called if the error includes: + // - an object of type input_error, and + // - an optional object of type leaf::e_errno (regardless of its .value), and + // - an object of type leaf::e_file_name. + []( input_error &, leaf::e_errno const * errn, leaf::e_file_name const & fn ) + { + std::cerr << "Failed to access " << fn.value; + if( errn ) + std::cerr << ", errno=" << *errn; + std::cerr << std::endl; + return 3; + }, - // This handler will be called if the error includes: - // - an object of type output_error, and - // - an object of type leaf::e_errno (regardless of its .value), - []( output_error &, leaf::e_errno const & errn ) - { - std::cerr << "Output error, errno=" << errn << std::endl; - return 4; - }, + // This handler will be called if the error includes: + // - an object of type output_error, and + // - an object of type leaf::e_errno (regardless of its .value), + []( output_error &, leaf::e_errno const & errn ) + { + std::cerr << "Output error, errno=" << errn << std::endl; + return 4; + }, - // This handler will be called if we've got a bad_command_line - []( bad_command_line & ) - { - std::cout << "Bad command line argument" << std::endl; - return 5; - }, + // This handler will be called if we've got a bad_command_line + []( bad_command_line & ) + { + std::cout << "Bad command line argument" << std::endl; + return 5; + }, - // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it - // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will - // never be called. - []( leaf::error_info const & unmatched ) - { - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - return 6; - } ); + // This last handler matches any error: it prints diagnostic information to help debug logic errors in the program, since it + // failed to match an appropriate error handler to the error condition it encountered. In this program this handler will + // never be called. + []( leaf::error_info const & unmatched ) + { + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + return 6; + } ); } @@ -150,58 +150,58 @@ int main( int argc, char const * argv[] ) // Parse the command line, return the file name. result parse_command_line( int argc, char const * argv[] ) { - if( argc==2 ) - return argv[1]; - else - return leaf::new_error(bad_command_line{}); + if( argc==2 ) + return argv[1]; + else + return leaf::new_error(bad_command_line{}); } // Open a file for reading. result> file_open( char const * file_name ) { - auto load = leaf::on_error(input_error{}); + auto load = leaf::on_error(input_error{}); - if( FILE * f = fopen(file_name, "rb") ) - return std::shared_ptr(f, &fclose); - else - return leaf::new_error(open_error{}, leaf::e_errno{errno}); + if( FILE * f = fopen(file_name, "rb") ) + return std::shared_ptr(f, &fclose); + else + return leaf::new_error(open_error{}, leaf::e_errno{errno}); } // Return the size of the file. result file_size( FILE & f ) { - auto load = leaf::on_error(input_error{}, size_error{}, []{ return leaf::e_errno{errno}; }); + auto load = leaf::on_error(input_error{}, size_error{}, []{ return leaf::e_errno{errno}; }); - if( fseek(&f, 0, SEEK_END) ) - return leaf::new_error(); + if( fseek(&f, 0, SEEK_END) ) + return leaf::new_error(); - int s = ftell(&f); - if( s==-1L ) - return leaf::new_error(); + int s = ftell(&f); + if( s==-1L ) + return leaf::new_error(); - if( fseek(&f,0,SEEK_SET) ) - return leaf::new_error(); + if( fseek(&f,0,SEEK_SET) ) + return leaf::new_error(); - return s; + return s; } // Read size bytes from f into buf. result file_read( FILE & f, void * buf, int size ) { - auto load = leaf::on_error(input_error{}); + auto load = leaf::on_error(input_error{}); - int n = fread(buf, 1, size, &f); + int n = fread(buf, 1, size, &f); - if( ferror(&f) ) - return leaf::new_error(read_error{}, leaf::e_errno{errno}); + if( ferror(&f) ) + return leaf::new_error(read_error{}, leaf::e_errno{errno}); - if( n!=size ) - return leaf::new_error(eof_error{}); + if( n!=size ) + return leaf::new_error(eof_error{}); - return { }; + return { }; } //////////////////////////////////////// @@ -210,17 +210,17 @@ result file_read( FILE & f, void * buf, int size ) namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/examples/print_half.cpp b/examples/print_half.cpp index a22a02b..0e0ec36 100644 --- a/examples/print_half.cpp +++ b/examples/print_half.cpp @@ -18,84 +18,84 @@ namespace leaf = boost::leaf; enum class ConversionErrc { - EmptyString = 1, - IllegalChar, - TooLong + EmptyString = 1, + IllegalChar, + TooLong }; leaf::result convert(const std::string& str) noexcept { - if (str.empty()) - return leaf::new_error(ConversionErrc::EmptyString); + if (str.empty()) + return leaf::new_error(ConversionErrc::EmptyString); - if (!std::all_of(str.begin(), str.end(), ::isdigit)) - return leaf::new_error(ConversionErrc::IllegalChar); + if (!std::all_of(str.begin(), str.end(), ::isdigit)) + return leaf::new_error(ConversionErrc::IllegalChar); - if (str.length() > 9) - return leaf::new_error(ConversionErrc::TooLong); + if (str.length() > 9) + return leaf::new_error(ConversionErrc::TooLong); - return atoi(str.c_str()); + return atoi(str.c_str()); } // Do not static_store BigInt to actually work -- it's a stub. struct BigInt { - static leaf::result fromString(const std::string& s) { return BigInt{s}; } - explicit BigInt(const std::string&) { } - BigInt half() const { return BigInt{""}; } - friend std::ostream& operator<<(std::ostream& o, const BigInt&) { return o << "big int half"; } + static leaf::result fromString(const std::string& s) { return BigInt{s}; } + explicit BigInt(const std::string&) { } + BigInt half() const { return BigInt{""}; } + friend std::ostream& operator<<(std::ostream& o, const BigInt&) { return o << "big int half"; } }; // This function handles ConversionErrc::TooLong errors, forwards any other error to the caller. leaf::result print_half(const std::string& text) { - return leaf::try_handle_some( - [&]() -> leaf::result - { - BOOST_LEAF_AUTO(r,convert(text)); - std::cout << r / 2 << std::endl; - return { }; - }, - [&]( leaf::match ) -> leaf::result - { - BOOST_LEAF_AUTO(i, BigInt::fromString(text)); - std::cout << i.half() << std::endl; - return { }; - } ); + return leaf::try_handle_some( + [&]() -> leaf::result + { + BOOST_LEAF_AUTO(r,convert(text)); + std::cout << r / 2 << std::endl; + return { }; + }, + [&]( leaf::match ) -> leaf::result + { + BOOST_LEAF_AUTO(i, BigInt::fromString(text)); + std::cout << i.half() << std::endl; + return { }; + } ); } int main( int argc, char const * argv[] ) { - return leaf::try_handle_all( - [&]() -> leaf::result - { - BOOST_LEAF_CHECK( print_half(argc<2 ? "" : argv[1]) ); - std::cout << "ok" << std::endl; - return 0; - }, + return leaf::try_handle_all( + [&]() -> leaf::result + { + BOOST_LEAF_CHECK( print_half(argc<2 ? "" : argv[1]) ); + std::cout << "ok" << std::endl; + return 0; + }, - []( leaf::match ) - { - std::cerr << "Empty string!" << std::endl; - return 1; - }, + []( leaf::match ) + { + std::cerr << "Empty string!" << std::endl; + return 1; + }, - []( leaf::match ) - { - std::cerr << "Illegal char!" << std::endl; - return 2; - }, + []( leaf::match ) + { + std::cerr << "Illegal char!" << std::endl; + return 2; + }, - []( leaf::error_info const & unmatched ) - { - // This will never execute in this program, but it would detect logic errors where an unknown error reaches main. - // In this case, we print diagnostic information. - std::cerr << - "Unknown failure detected" << std::endl << - "Cryptic diagnostic information follows" << std::endl << - unmatched; - return 3; - } ); + []( leaf::error_info const & unmatched ) + { + // This will never execute in this program, but it would detect logic errors where an unknown error reaches main. + // In this case, we print diagnostic information. + std::cerr << + "Unknown failure detected" << std::endl << + "Cryptic diagnostic information follows" << std::endl << + unmatched; + return 3; + } ); } //////////////////////////////////////// @@ -104,17 +104,17 @@ int main( int argc, char const * argv[] ) namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) - { - std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); - std::terminate(); - } + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e ) + { + std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what(); + std::terminate(); + } - struct source_location; - BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) - { - throw_exception(e); - } + struct source_location; + BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & ) + { + throw_exception(e); + } } #endif diff --git a/include/boost/leaf.hpp b/include/boost/leaf.hpp index e05b12b..94cf84b 100644 --- a/include/boost/leaf.hpp +++ b/include/boost/leaf.hpp @@ -17,13 +17,13 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif // >>> #include @@ -37,13 +37,13 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif // >>> #include @@ -57,13 +57,13 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif // >>> #include @@ -77,13 +77,13 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif // >>> #include @@ -397,79 +397,79 @@ template class F, class... T> using mp_valid = typename detai namespace boost { namespace leaf { - namespace leaf_detail - { - template - struct gcc49_workaround //Thanks Glen Fernandes - { - using type = void; - }; + namespace leaf_detail + { + template + struct gcc49_workaround //Thanks Glen Fernandes + { + using type = void; + }; - template - using void_t = typename gcc49_workaround::type; + template + using void_t = typename gcc49_workaround::type; - template - struct function_traits - { - constexpr static int arity = -1; - }; + template + struct function_traits + { + constexpr static int arity = -1; + }; - template - struct function_traits> - { - private: + template + struct function_traits> + { + private: - using tr = function_traits; + using tr = function_traits; - public: + public: - using return_type = typename tr::return_type; - static constexpr int arity = tr::arity - 1; + using return_type = typename tr::return_type; + static constexpr int arity = tr::arity - 1; - using mp_args = typename leaf_detail_mp11::mp_rest; + using mp_args = typename leaf_detail_mp11::mp_rest; - template - struct arg: - tr::template arg - { - }; - }; + template + struct arg: + tr::template arg + { + }; + }; - template - struct function_traits - { - using return_type = R; - static constexpr int arity = sizeof...(A); + template + struct function_traits + { + using return_type = R; + static constexpr int arity = sizeof...(A); - using mp_args = leaf_detail_mp11::mp_list; + using mp_args = leaf_detail_mp11::mp_list; - template - struct arg - { - static_assert(I < arity, "I out of range"); - using type = typename std::tuple_element>::type; - }; - }; + template + struct arg + { + static_assert(I < arity, "I out of range"); + using type = typename std::tuple_element>::type; + }; + }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; - template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; + template struct function_traits : function_traits { }; - template - using fn_return_type = typename function_traits::return_type; + template + using fn_return_type = typename function_traits::return_type; - template - using fn_arg_type = typename function_traits::template arg::type; + template + using fn_arg_type = typename function_traits::template arg::type; - template - using fn_mp_args = typename function_traits::mp_args; + template + using fn_mp_args = typename function_traits::mp_args; - } + } } } @@ -487,13 +487,13 @@ namespace boost { namespace leaf { // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif // >>> #include @@ -507,13 +507,13 @@ namespace boost { namespace leaf { // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif // >>> #include @@ -533,13 +533,13 @@ namespace boost { namespace leaf { // (C) Copyright Guillaume Melquiond 2003. #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif //////////////////////////////////////// @@ -547,98 +547,98 @@ namespace boost { namespace leaf { // Configure BOOST_LEAF_NO_EXCEPTIONS, unless already #defined #ifndef BOOST_LEAF_NO_EXCEPTIONS -# if defined(__clang__) && !defined(__ibmxl__) -// Clang C++ emulates GCC, so it has to appear early. +# if defined(__clang__) && !defined(__ibmxl__) +// Clang C++ emulates GCC, so it has to appear early. -# if !__has_feature(cxx_exceptions) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !__has_feature(cxx_exceptions) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__DMC__) -// Digital Mars C++ +# elif defined(__DMC__) +// Digital Mars C++ -# if !defined(_CPPUNWIND) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !defined(_CPPUNWIND) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__GNUC__) && !defined(__ibmxl__) -// GNU C++: +# elif defined(__GNUC__) && !defined(__ibmxl__) +// GNU C++: -# if !defined(__EXCEPTIONS) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__KCC) -// Kai C++ +# elif defined(__KCC) +// Kai C++ -# if !defined(_EXCEPTIONS) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !defined(_EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__CODEGEARC__) -// CodeGear - must be checked for before Borland +# elif defined(__CODEGEARC__) +// CodeGear - must be checked for before Borland -# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__BORLANDC__) -// Borland +# elif defined(__BORLANDC__) +// Borland -# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__MWERKS__) -// Metrowerks CodeWarrior +# elif defined(__MWERKS__) +// Metrowerks CodeWarrior -# if !__option(exceptions) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !__option(exceptions) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__) -// IBM z/OS XL C/C++ +# elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__) +// IBM z/OS XL C/C++ -# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(__ibmxl__) -// IBM XL C/C++ for Linux (Little Endian) +# elif defined(__ibmxl__) +// IBM XL C/C++ for Linux (Little Endian) -# if !__has_feature(cxx_exceptions) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif +# if !__has_feature(cxx_exceptions) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif -# elif defined(_MSC_VER) -// Microsoft Visual C++ +# elif defined(_MSC_VER) +// Microsoft Visual C++ // -// Must remain the last #elif since some other vendors (Metrowerks, for -// example) also #define _MSC_VER +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER -# if !defined(_CPPUNWIND) -# define BOOST_LEAF_NO_EXCEPTIONS -# endif -# endif +# if !defined(_CPPUNWIND) +# define BOOST_LEAF_NO_EXCEPTIONS +# endif +# endif #endif #ifdef BOOST_NORETURN -# define BOOST_LEAF_NORETURN BOOST_NORETURN +# define BOOST_LEAF_NORETURN BOOST_NORETURN #else -# if defined(_MSC_VER) -# define BOOST_LEAF_NORETURN __declspec(noreturn) -# elif defined(__GNUC__) -# define BOOST_LEAF_NORETURN __attribute__ ((__noreturn__)) -# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) -# if __has_attribute(noreturn) -# define BOOST_LEAF_NORETURN [[noreturn]] -# endif -# elif defined(__has_cpp_attribute) -# if __has_cpp_attribute(noreturn) -# define BOOST_LEAF_NORETURN [[noreturn]] -# endif -# endif +# if defined(_MSC_VER) +# define BOOST_LEAF_NORETURN __declspec(noreturn) +# elif defined(__GNUC__) +# define BOOST_LEAF_NORETURN __attribute__ ((__noreturn__)) +# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) +# if __has_attribute(noreturn) +# define BOOST_LEAF_NORETURN [[noreturn]] +# endif +# elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(noreturn) +# define BOOST_LEAF_NORETURN [[noreturn]] +# endif +# endif #endif #if !defined(BOOST_LEAF_NORETURN) # define BOOST_LEAF_NORETURN @@ -647,50 +647,50 @@ namespace boost { namespace leaf { //////////////////////////////////////// #ifndef BOOST_LEAF_DIAGNOSTICS -# define BOOST_LEAF_DIAGNOSTICS 1 +# define BOOST_LEAF_DIAGNOSTICS 1 #endif #if BOOST_LEAF_DIAGNOSTICS!=0 && BOOST_LEAF_DIAGNOSTICS!=1 -# error BOOST_LEAF_DIAGNOSTICS must be 0 or 1. +# error BOOST_LEAF_DIAGNOSTICS must be 0 or 1. #endif //////////////////////////////////////// #ifdef _MSC_VER -# define BOOST_LEAF_ALWAYS_INLINE __forceinline +# define BOOST_LEAF_ALWAYS_INLINE __forceinline #else -# define BOOST_LEAF_ALWAYS_INLINE __attribute__((always_inline)) inline +# define BOOST_LEAF_ALWAYS_INLINE __attribute__((always_inline)) inline #endif //////////////////////////////////////// #ifndef BOOST_LEAF_NODISCARD -# if __cplusplus >= 201703L -# define BOOST_LEAF_NODISCARD [[nodiscard]] -# else -# define BOOST_LEAF_NODISCARD -# endif +# if __cplusplus >= 201703L +# define BOOST_LEAF_NODISCARD [[nodiscard]] +# else +# define BOOST_LEAF_NODISCARD +# endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_CONSTEXPR -# if __cplusplus > 201402L -# define BOOST_LEAF_CONSTEXPR constexpr -# else -# define BOOST_LEAF_CONSTEXPR -# endif +# if __cplusplus > 201402L +# define BOOST_LEAF_CONSTEXPR constexpr +# else +# define BOOST_LEAF_CONSTEXPR +# endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_ASSERT -# ifdef BOOST_ASSERT -# define BOOST_LEAF_ASSERT BOOST_ASSERT -# else +# ifdef BOOST_ASSERT +# define BOOST_LEAF_ASSERT BOOST_ASSERT +# else # include # define BOOST_LEAF_ASSERT assert -# endif +# endif #endif //////////////////////////////////////// @@ -698,9 +698,9 @@ namespace boost { namespace leaf { #ifndef BOOST_LEAF_NO_EXCEPTIONS # include # if (defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L) || (defined(_MSC_VER) && _MSC_VER >= 1900) -# define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 1 +# define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 1 # else -# define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 0 +# define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 0 # endif #endif @@ -712,158 +712,158 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - namespace leaf_detail - { - template - class optional - { - int key_; - union { T value_; }; + namespace leaf_detail + { + template + class optional + { + int key_; + union { T value_; }; - public: + public: - typedef T value_type; + typedef T value_type; - BOOST_LEAF_CONSTEXPR optional() noexcept: - key_(0) - { - } + BOOST_LEAF_CONSTEXPR optional() noexcept: + key_(0) + { + } - BOOST_LEAF_CONSTEXPR optional( optional const & x ): - key_(x.key_) - { - if( x.key_ ) - (void) new (&value_) T( x.value_ ); - } + BOOST_LEAF_CONSTEXPR optional( optional const & x ): + key_(x.key_) + { + if( x.key_ ) + (void) new (&value_) T( x.value_ ); + } - BOOST_LEAF_CONSTEXPR optional( optional && x ) noexcept: - key_(x.key_) - { - if( x.key_ ) - { - (void) new (&value_) T( std::move(x.value_) ); - x.reset(); - } - } + BOOST_LEAF_CONSTEXPR optional( optional && x ) noexcept: + key_(x.key_) + { + if( x.key_ ) + { + (void) new (&value_) T( std::move(x.value_) ); + x.reset(); + } + } - BOOST_LEAF_CONSTEXPR optional( int key, T const & v ): - key_(key), - value_(v) - { - BOOST_LEAF_ASSERT(!empty()); - } + BOOST_LEAF_CONSTEXPR optional( int key, T const & v ): + key_(key), + value_(v) + { + BOOST_LEAF_ASSERT(!empty()); + } - BOOST_LEAF_CONSTEXPR optional( int key, T && v ) noexcept: - key_(key), - value_(std::move(v)) - { - BOOST_LEAF_ASSERT(!empty()); - } + BOOST_LEAF_CONSTEXPR optional( int key, T && v ) noexcept: + key_(key), + value_(std::move(v)) + { + BOOST_LEAF_ASSERT(!empty()); + } - BOOST_LEAF_CONSTEXPR optional & operator=( optional const & x ) - { - reset(); - if( int key = x.key() ) - { - put(key, x.value_); - key_ = key; - } - return *this; - } + BOOST_LEAF_CONSTEXPR optional & operator=( optional const & x ) + { + reset(); + if( int key = x.key() ) + { + put(key, x.value_); + key_ = key; + } + return *this; + } - BOOST_LEAF_CONSTEXPR optional & operator=( optional && x ) noexcept - { - reset(); - if( int key = x.key() ) - { - put(key, std::move(x.value_)); - x.reset(); - } - return *this; - } + BOOST_LEAF_CONSTEXPR optional & operator=( optional && x ) noexcept + { + reset(); + if( int key = x.key() ) + { + put(key, std::move(x.value_)); + x.reset(); + } + return *this; + } - ~optional() noexcept - { - reset(); - } + ~optional() noexcept + { + reset(); + } - BOOST_LEAF_CONSTEXPR bool empty() const noexcept - { - return key_==0; - } + BOOST_LEAF_CONSTEXPR bool empty() const noexcept + { + return key_==0; + } - BOOST_LEAF_CONSTEXPR int key() const noexcept - { - return key_; - } + BOOST_LEAF_CONSTEXPR int key() const noexcept + { + return key_; + } - BOOST_LEAF_CONSTEXPR void reset() noexcept - { - if( key_ ) - { - value_.~T(); - key_=0; - } - } + BOOST_LEAF_CONSTEXPR void reset() noexcept + { + if( key_ ) + { + value_.~T(); + key_=0; + } + } - BOOST_LEAF_CONSTEXPR T & put( int key, T const & v ) - { - BOOST_LEAF_ASSERT(key); - reset(); - (void) new(&value_) T(v); - key_=key; - return value_; - } + BOOST_LEAF_CONSTEXPR T & put( int key, T const & v ) + { + BOOST_LEAF_ASSERT(key); + reset(); + (void) new(&value_) T(v); + key_=key; + return value_; + } - BOOST_LEAF_CONSTEXPR T & put( int key, T && v ) noexcept - { - BOOST_LEAF_ASSERT(key); - reset(); - (void) new(&value_) T(std::move(v)); - key_=key; - return value_; - } + BOOST_LEAF_CONSTEXPR T & put( int key, T && v ) noexcept + { + BOOST_LEAF_ASSERT(key); + reset(); + (void) new(&value_) T(std::move(v)); + key_=key; + return value_; + } - BOOST_LEAF_CONSTEXPR T const * has_value(int key) const noexcept - { - BOOST_LEAF_ASSERT(key); - return key_==key ? &value_ : 0; - } + BOOST_LEAF_CONSTEXPR T const * has_value(int key) const noexcept + { + BOOST_LEAF_ASSERT(key); + return key_==key ? &value_ : 0; + } - BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept - { - BOOST_LEAF_ASSERT(key); - return key_==key ? &value_ : 0; - } + BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept + { + BOOST_LEAF_ASSERT(key); + return key_==key ? &value_ : 0; + } - BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept - { - BOOST_LEAF_ASSERT(has_value(key) != 0); - return value_; - } + BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + return value_; + } - BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept - { - BOOST_LEAF_ASSERT(has_value(key) != 0); - return value_; - } + BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + return value_; + } - BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept - { - BOOST_LEAF_ASSERT(has_value(key) != 0); - return value_; - } + BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + return value_; + } - BOOST_LEAF_CONSTEXPR T value(int key) && noexcept - { - BOOST_LEAF_ASSERT(has_value(key) != 0); - T tmp(std::move(value_)); - reset(); - return tmp; - } - }; + BOOST_LEAF_CONSTEXPR T value(int key) && noexcept + { + BOOST_LEAF_ASSERT(has_value(key) != 0); + T tmp(std::move(value_)); + reset(); + return tmp; + } + }; - } + } } } @@ -875,112 +875,112 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - namespace leaf_detail - { - template - BOOST_LEAF_CONSTEXPR inline char const * check_prefix( char const * t, char const (&prefix)[N] ) - { - return std::strncmp(t,prefix,sizeof(prefix)-1)==0 ? t+sizeof(prefix)-1 : t; - } - } + namespace leaf_detail + { + template + BOOST_LEAF_CONSTEXPR inline char const * check_prefix( char const * t, char const (&prefix)[N] ) + { + return std::strncmp(t,prefix,sizeof(prefix)-1)==0 ? t+sizeof(prefix)-1 : t; + } + } - template - inline char const * type() - { - using leaf_detail::check_prefix; - char const * t = + template + inline char const * type() + { + using leaf_detail::check_prefix; + char const * t = #ifdef __FUNCSIG__ - __FUNCSIG__; + __FUNCSIG__; #else - __PRETTY_FUNCTION__; + __PRETTY_FUNCTION__; #endif #if defined(__clang__) - BOOST_LEAF_ASSERT(check_prefix(t,"const char *boost::leaf::type() ")==t+32); - return t+32; + BOOST_LEAF_ASSERT(check_prefix(t,"const char *boost::leaf::type() ")==t+32); + return t+32; #elif defined(__GNUC__) - BOOST_LEAF_ASSERT(check_prefix(t,"const char* boost::leaf::type() ")==t+32); - return t+32; + BOOST_LEAF_ASSERT(check_prefix(t,"const char* boost::leaf::type() ")==t+32); + return t+32; #else - char const * clang_style = check_prefix(t,"const char *boost::leaf::type() "); - if( clang_style!=t ) - return clang_style; - char const * gcc_style = check_prefix(t,"const char* boost::leaf::type() "); - if( gcc_style!=t ) - return gcc_style; + char const * clang_style = check_prefix(t,"const char *boost::leaf::type() "); + if( clang_style!=t ) + return clang_style; + char const * gcc_style = check_prefix(t,"const char* boost::leaf::type() "); + if( gcc_style!=t ) + return gcc_style; #endif - return t; - } + return t; + } - namespace leaf_detail - { - template - struct is_printable: std::false_type - { - }; + namespace leaf_detail + { + template + struct is_printable: std::false_type + { + }; - template - struct is_printable()<(), void())>: std::true_type - { - }; + template + struct is_printable()<(), void())>: std::true_type + { + }; - //////////////////////////////////////// + //////////////////////////////////////// - template - struct has_printable_member_value: std::false_type - { - }; + template + struct has_printable_member_value: std::false_type + { + }; - template - struct has_printable_member_value()<().value, void())>: std::true_type - { - }; + template + struct has_printable_member_value()<().value, void())>: std::true_type + { + }; - //////////////////////////////////////// + //////////////////////////////////////// - template ::value, bool ValuePrintable=has_printable_member_value::value> - struct diagnostic; + template ::value, bool ValuePrintable=has_printable_member_value::value> + struct diagnostic; - template - struct diagnostic - { - static constexpr bool is_invisible = false; - static void print( std::ostream & os, Wrapper const & x ) - { - os << x; - } - }; + template + struct diagnostic + { + static constexpr bool is_invisible = false; + static void print( std::ostream & os, Wrapper const & x ) + { + os << x; + } + }; - template - struct diagnostic - { - static constexpr bool is_invisible = false; - static void print( std::ostream & os, Wrapper const & x ) - { - os << type() << ": " << x.value; - } - }; + template + struct diagnostic + { + static constexpr bool is_invisible = false; + static void print( std::ostream & os, Wrapper const & x ) + { + os << type() << ": " << x.value; + } + }; - template - struct diagnostic - { - static constexpr bool is_invisible = false; - static void print( std::ostream & os, Wrapper const & ) - { - os << type() << ": {Non-Printable}"; - } - }; + template + struct diagnostic + { + static constexpr bool is_invisible = false; + static void print( std::ostream & os, Wrapper const & ) + { + os << type() << ": {Non-Printable}"; + } + }; #ifndef BOOST_LEAF_NO_EXCEPTIONS - template <> - struct diagnostic - { - static constexpr bool is_invisible = true; - BOOST_LEAF_CONSTEXPR static void print( std::ostream &, std::exception_ptr const & ) - { - } - }; + template <> + struct diagnostic + { + static constexpr bool is_invisible = true; + BOOST_LEAF_CONSTEXPR static void print( std::ostream &, std::exception_ptr const & ) + { + } + }; #endif - } + } } } @@ -997,43 +997,43 @@ namespace boost { namespace leaf { #define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y) #define BOOST_LEAF_ASSIGN(v,r)\ - static_assert(::boost::leaf::is_result_type::type>::value, "The BOOST_LEAF_ASSIGN macro requires a result type as the second argument");\ - auto && BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__) = r;\ - if( !BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__) )\ - return BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__).error();\ - v = BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__).value() + static_assert(::boost::leaf::is_result_type::type>::value, "The BOOST_LEAF_ASSIGN macro requires a result type as the second argument");\ + auto && BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__) = r;\ + if( !BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__) )\ + return BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__).error();\ + v = BOOST_LEAF_TOKEN_PASTE2(boost_leaf_temp_, __LINE__).value() #define BOOST_LEAF_AUTO(v, r)\ - BOOST_LEAF_ASSIGN(auto && v, r) + BOOST_LEAF_ASSIGN(auto && v, r) #define BOOST_LEAF_CHECK(r)\ - {\ - static_assert(::boost::leaf::is_result_type::type>::value, "BOOST_LEAF_CHECK requires a result type");\ - auto && _r = r;\ - if( !_r )\ - return _r.error();\ - } + {\ + static_assert(::boost::leaf::is_result_type::type>::value, "BOOST_LEAF_CHECK requires a result type");\ + auto && _r = r;\ + if( !_r )\ + return _r.error();\ + } #define BOOST_LEAF_NEW_ERROR ::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error namespace boost { namespace leaf { - namespace leaf_detail - { - struct inject_loc - { - char const * const file; - int const line; - char const * const fn; + namespace leaf_detail + { + struct inject_loc + { + char const * const file; + int const line; + char const * const fn; - template - friend T operator+( inject_loc loc, T && x ) noexcept - { - x.load_source_location_(loc.file, loc.line, loc.fn); - return std::move(x); - } - }; - } + template + friend T operator+( inject_loc loc, T && x ) noexcept + { + x.load_source_location_(loc.file, loc.line, loc.fn); + return std::move(x); + } + }; + } } } @@ -1043,16 +1043,16 @@ namespace boost { namespace leaf { namespace boost { - BOOST_LEAF_NORETURN void throw_exception( std::exception const & ); // user defined + BOOST_LEAF_NORETURN void throw_exception( std::exception const & ); // user defined } namespace boost { namespace leaf { - template - BOOST_LEAF_NORETURN void throw_exception( T const & e ) - { - ::boost::throw_exception(e); - } + template + BOOST_LEAF_NORETURN void throw_exception( T const & e ) + { + ::boost::throw_exception(e); + } } } @@ -1060,11 +1060,11 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - template - BOOST_LEAF_NORETURN void throw_exception( T const & e ) - { - throw e; - } + template + BOOST_LEAF_NORETURN void throw_exception( T const & e ) + { + throw e; + } } } @@ -1073,23 +1073,23 @@ namespace boost { namespace leaf { //////////////////////////////////////// #ifdef BOOST_LEAF_NO_THREADS -# define BOOST_LEAF_THREAD_LOCAL - namespace boost { namespace leaf { - namespace leaf_detail - { - using atomic_unsigned_int = unsigned int; - } - } } +# define BOOST_LEAF_THREAD_LOCAL + namespace boost { namespace leaf { + namespace leaf_detail + { + using atomic_unsigned_int = unsigned int; + } + } } #else -# include -# include -# define BOOST_LEAF_THREAD_LOCAL thread_local - namespace boost { namespace leaf { - namespace leaf_detail - { - using atomic_unsigned_int = std::atomic; - } - } } +# include +# include +# define BOOST_LEAF_THREAD_LOCAL thread_local + namespace boost { namespace leaf { + namespace leaf_detail + { + using atomic_unsigned_int = std::atomic; + } + } } #endif //////////////////////////////////////// @@ -1098,86 +1098,86 @@ namespace boost { namespace leaf { #if BOOST_LEAF_DIAGNOSTICS - namespace leaf_detail - { - class e_unexpected_count - { - public: + namespace leaf_detail + { + class e_unexpected_count + { + public: - char const * (*first_type)(); - int count; + char const * (*first_type)(); + int count; - BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*first_type)()) noexcept: - first_type(first_type), - count(1) - { - } + BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*first_type)()) noexcept: + first_type(first_type), + count(1) + { + } - void print(std::ostream & os) const - { - BOOST_LEAF_ASSERT(first_type != 0); - BOOST_LEAF_ASSERT(count>0); - os << "Detected "; - if( count==1 ) - os << "1 attempt to communicate an unexpected error object"; - else - os << count << " attempts to communicate unexpected error objects, the first one"; - os << " of type " << first_type() << std::endl; - } - }; + void print(std::ostream & os) const + { + BOOST_LEAF_ASSERT(first_type != 0); + BOOST_LEAF_ASSERT(count>0); + os << "Detected "; + if( count==1 ) + os << "1 attempt to communicate an unexpected error object"; + else + os << count << " attempts to communicate unexpected error objects, the first one"; + os << " of type " << first_type() << std::endl; + } + }; - template <> - struct diagnostic - { - static constexpr bool is_invisible = true; - BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_count const &) noexcept { } - }; + template <> + struct diagnostic + { + static constexpr bool is_invisible = true; + BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_count const &) noexcept { } + }; - class e_unexpected_info - { - std::string s_; - std::set already_; + class e_unexpected_info + { + std::string s_; + std::set already_; - public: + public: - e_unexpected_info() noexcept - { - } + e_unexpected_info() noexcept + { + } - template - void add(E && e) - { - if( !diagnostic::is_invisible && already_.insert(&type).second ) - { - std::stringstream s; - diagnostic::print(s,e); - s << std::endl; - s_ += s.str(); - } - } + template + void add(E && e) + { + if( !diagnostic::is_invisible && already_.insert(&type).second ) + { + std::stringstream s; + diagnostic::print(s,e); + s << std::endl; + s_ += s.str(); + } + } - void print(std::ostream & os) const - { - os << "Unhandled error objects:\n" << s_; - } - }; + void print(std::ostream & os) const + { + os << "Unhandled error objects:\n" << s_; + } + }; - template <> - struct diagnostic - { - static constexpr bool is_invisible = true; - BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_info const &) noexcept { } - }; + template <> + struct diagnostic + { + static constexpr bool is_invisible = true; + BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_info const &) noexcept { } + }; - template - struct tl_unexpected_enabled - { - static BOOST_LEAF_THREAD_LOCAL int counter; - }; + template + struct tl_unexpected_enabled + { + static BOOST_LEAF_THREAD_LOCAL int counter; + }; - template - BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled::counter; - } + template + BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled::counter; + } #endif @@ -1187,539 +1187,539 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - struct e_source_location - { - char const * const file; - int const line; - char const * const function; + struct e_source_location + { + char const * const file; + int const line; + char const * const function; - friend std::ostream & operator<<( std::ostream & os, e_source_location const & x ) - { - return os << leaf::type() << ": " << x.file << '(' << x.line << ") in function " << x.function; - } - }; + friend std::ostream & operator<<( std::ostream & os, e_source_location const & x ) + { + return os << leaf::type() << ": " << x.file << '(' << x.line << ") in function " << x.function; + } + }; - //////////////////////////////////////// + //////////////////////////////////////// - namespace leaf_detail - { - template - class slot; + namespace leaf_detail + { + template + class slot; - template - struct tl_slot_ptr - { - static BOOST_LEAF_THREAD_LOCAL slot * p; - }; + template + struct tl_slot_ptr + { + static BOOST_LEAF_THREAD_LOCAL slot * p; + }; - template - BOOST_LEAF_THREAD_LOCAL slot * tl_slot_ptr::p; + template + BOOST_LEAF_THREAD_LOCAL slot * tl_slot_ptr::p; - template - class slot: - optional - { - slot( slot const & ) = delete; - slot & operator=( slot const & ) = delete; + template + class slot: + optional + { + slot( slot const & ) = delete; + slot & operator=( slot const & ) = delete; - using impl = optional; - slot * * top_; - slot * prev_; + using impl = optional; + slot * * top_; + slot * prev_; - public: + public: - BOOST_LEAF_CONSTEXPR slot() noexcept: - top_(0) - { - } + BOOST_LEAF_CONSTEXPR slot() noexcept: + top_(0) + { + } - BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept: - optional(std::move(x)), - top_(0) - { - BOOST_LEAF_ASSERT(x.top_==0); - } + BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept: + optional(std::move(x)), + top_(0) + { + BOOST_LEAF_ASSERT(x.top_==0); + } - BOOST_LEAF_CONSTEXPR void activate() noexcept - { - BOOST_LEAF_ASSERT(top_==0 || *top_!=this); - top_ = &tl_slot_ptr::p; - prev_ = *top_; - *top_ = this; - } + BOOST_LEAF_CONSTEXPR void activate() noexcept + { + BOOST_LEAF_ASSERT(top_==0 || *top_!=this); + top_ = &tl_slot_ptr::p; + prev_ = *top_; + *top_ = this; + } - BOOST_LEAF_CONSTEXPR void deactivate() noexcept - { - BOOST_LEAF_ASSERT(top_!=0 && *top_==this); - *top_ = prev_; - } + BOOST_LEAF_CONSTEXPR void deactivate() noexcept + { + BOOST_LEAF_ASSERT(top_!=0 && *top_==this); + *top_ = prev_; + } - BOOST_LEAF_CONSTEXPR void propagate() noexcept; + BOOST_LEAF_CONSTEXPR void propagate() noexcept; - void print( std::ostream & os, int key_to_print ) const - { - if( !diagnostic::is_invisible ) - if( int k = this->key() ) - { - if( key_to_print ) - { - if( key_to_print!=k ) - return; - } - else - os << '[' << k << ']'; - diagnostic::print(os, value(k)); - os << std::endl; - } - } + void print( std::ostream & os, int key_to_print ) const + { + if( !diagnostic::is_invisible ) + if( int k = this->key() ) + { + if( key_to_print ) + { + if( key_to_print!=k ) + return; + } + else + os << '[' << k << ']'; + diagnostic::print(os, value(k)); + os << std::endl; + } + } - using impl::put; - using impl::has_value; - using impl::value; - }; + using impl::put; + using impl::has_value; + using impl::value; + }; #if BOOST_LEAF_DIAGNOSTICS - template - BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept - { - if( slot * sl = tl_slot_ptr::p ) - if( e_unexpected_count * unx = sl->has_value(err_id) ) - ++unx->count; - else - sl->put(err_id, e_unexpected_count(&type)); - } + template + BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept + { + if( slot * sl = tl_slot_ptr::p ) + if( e_unexpected_count * unx = sl->has_value(err_id) ) + ++unx->count; + else + sl->put(err_id, e_unexpected_count(&type)); + } - template - BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept - { - if( slot * sl = tl_slot_ptr::p ) - if( e_unexpected_info * unx = sl->has_value(err_id) ) - unx->add(std::forward(e)); - else - sl->put(err_id, e_unexpected_info()).add(std::forward(e)); - } + template + BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept + { + if( slot * sl = tl_slot_ptr::p ) + if( e_unexpected_info * unx = sl->has_value(err_id) ) + unx->add(std::forward(e)); + else + sl->put(err_id, e_unexpected_info()).add(std::forward(e)); + } - template - BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept - { - load_unexpected_count(err_id); - load_unexpected_info(err_id, std::forward(e)); - } + template + BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept + { + load_unexpected_count(err_id); + load_unexpected_info(err_id, std::forward(e)); + } #endif - template - BOOST_LEAF_CONSTEXPR inline void slot::propagate() noexcept - { - BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this)); - if( prev_ ) - { - impl & that_ = *prev_; - if( that_.empty() ) - { - impl & this_ = *this; - that_ = std::move(this_); - } - } + template + BOOST_LEAF_CONSTEXPR inline void slot::propagate() noexcept + { + BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this)); + if( prev_ ) + { + impl & that_ = *prev_; + if( that_.empty() ) + { + impl & this_ = *this; + that_ = std::move(this_); + } + } #if BOOST_LEAF_DIAGNOSTICS - else - { - int c = tl_unexpected_enabled<>::counter; - BOOST_LEAF_ASSERT(c>=0); - if( c ) - if( int err_id = impl::key() ) - load_unexpected(err_id, std::move(*this).value(err_id)); - } + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + if( int err_id = impl::key() ) + load_unexpected(err_id, std::move(*this).value(err_id)); + } #endif - } + } - template - BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept - { - static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); - using T = typename std::decay::type; - BOOST_LEAF_ASSERT((err_id&3)==1); - if( slot * p = tl_slot_ptr::p ) - (void) p->put(err_id, std::forward(e)); + template + BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept + { + static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); + using T = typename std::decay::type; + BOOST_LEAF_ASSERT((err_id&3)==1); + if( slot * p = tl_slot_ptr::p ) + (void) p->put(err_id, std::forward(e)); #if BOOST_LEAF_DIAGNOSTICS - else - { - int c = tl_unexpected_enabled<>::counter; - BOOST_LEAF_ASSERT(c>=0); - if( c ) - load_unexpected(err_id, std::forward(e)); - } + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + load_unexpected(err_id, std::forward(e)); + } #endif - return 0; - } + return 0; + } - template - BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept - { - 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; - static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); - BOOST_LEAF_ASSERT((err_id&3)==1); - if( auto sl = tl_slot_ptr::p ) - if( auto v = sl->has_value(err_id) ) - (void) std::forward(f)(*v); - else - (void) std::forward(f)(sl->put(err_id,E())); - return 0; - } - } + template + BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept + { + 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; + static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); + BOOST_LEAF_ASSERT((err_id&3)==1); + if( auto sl = tl_slot_ptr::p ) + if( auto v = sl->has_value(err_id) ) + (void) std::forward(f)(*v); + else + (void) std::forward(f)(sl->put(err_id,E())); + return 0; + } + } - //////////////////////////////////////// + //////////////////////////////////////// - namespace leaf_detail - { - template - struct id_factory - { - static atomic_unsigned_int counter; - static BOOST_LEAF_THREAD_LOCAL unsigned current_id; + namespace leaf_detail + { + template + struct id_factory + { + static atomic_unsigned_int counter; + static BOOST_LEAF_THREAD_LOCAL unsigned current_id; - BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept - { - auto id = (counter+=4); - BOOST_LEAF_ASSERT((id&3)==1); - return id; - } - }; + BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept + { + auto id = (counter+=4); + BOOST_LEAF_ASSERT((id&3)==1); + return id; + } + }; - template - atomic_unsigned_int id_factory::counter(-3); + template + atomic_unsigned_int id_factory::counter(-3); - template - BOOST_LEAF_THREAD_LOCAL unsigned id_factory::current_id(0); + template + BOOST_LEAF_THREAD_LOCAL unsigned id_factory::current_id(0); - inline int current_id() noexcept - { - auto id = id_factory<>::current_id; - BOOST_LEAF_ASSERT(id==0 || (id&3)==1); - return id; - } + inline int current_id() noexcept + { + auto id = id_factory<>::current_id; + BOOST_LEAF_ASSERT(id==0 || (id&3)==1); + return id; + } - inline int new_id() noexcept - { - auto id = id_factory<>::generate_next_id(); - return id_factory<>::current_id = id; - } - } + inline int new_id() noexcept + { + auto id = id_factory<>::generate_next_id(); + return id_factory<>::current_id = id; + } + } - //////////////////////////////////////// + //////////////////////////////////////// - namespace leaf_detail - { - template ::arity> - struct load_item - { - static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument"); - }; + namespace leaf_detail + { + template ::arity> + struct load_item + { + static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument"); + }; - template - struct load_item - { - BOOST_LEAF_CONSTEXPR static int load( int err_id, E && e ) noexcept - { - return load_slot(err_id, std::forward(e)); - } - }; + template + struct load_item + { + BOOST_LEAF_CONSTEXPR static int load( int err_id, E && e ) noexcept + { + return load_slot(err_id, std::forward(e)); + } + }; - template - struct load_item - { - BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept - { - return load_slot(err_id, std::forward(f)()); - } - }; + template + struct load_item + { + BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept + { + return load_slot(err_id, std::forward(f)()); + } + }; - template - struct load_item - { - BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept - { - return accumulate_slot(err_id, std::forward(f)); - } - }; - } + template + struct load_item + { + BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept + { + return accumulate_slot(err_id, std::forward(f)); + } + }; + } - //////////////////////////////////////// + //////////////////////////////////////// - namespace leaf_detail - { - class leaf_category final: public std::error_category - { - bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; } - bool equivalent( std::error_code const &, int ) const noexcept final override { return false; } - char const * name() const noexcept final override { return "LEAF error"; } - std::string message( int condition ) const final override { return name(); } - public: - ~leaf_category() noexcept final override { } - }; + namespace leaf_detail + { + class leaf_category final: public std::error_category + { + bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; } + bool equivalent( std::error_code const &, int ) const noexcept final override { return false; } + char const * name() const noexcept final override { return "LEAF error"; } + std::string message( int condition ) const final override { return name(); } + public: + ~leaf_category() noexcept final override { } + }; - template - struct get_error_category - { - static leaf_category cat; - }; + template + struct get_error_category + { + static leaf_category cat; + }; - template - leaf_category get_error_category::cat; + template + leaf_category get_error_category::cat; - inline int import_error_code( std::error_code const & ec ) noexcept - { - if( int err_id = ec.value() ) - { - std::error_category const & cat = get_error_category<>::cat; - if( &ec.category()==&cat ) - { - BOOST_LEAF_ASSERT((err_id&3)==1); - return (err_id&~3)|1; - } - else - { - err_id = new_id(); - (void) load_slot(err_id, ec); - return (err_id&~3)|1; - } - } - else - return 0; - } - } + inline int import_error_code( std::error_code const & ec ) noexcept + { + if( int err_id = ec.value() ) + { + std::error_category const & cat = get_error_category<>::cat; + if( &ec.category()==&cat ) + { + BOOST_LEAF_ASSERT((err_id&3)==1); + return (err_id&~3)|1; + } + else + { + err_id = new_id(); + (void) load_slot(err_id, ec); + return (err_id&~3)|1; + } + } + else + return 0; + } + } - inline bool is_error_id( std::error_code const & ec ) noexcept - { - bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat); - BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1)); - return res; - } + inline bool is_error_id( std::error_code const & ec ) noexcept + { + bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat); + BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1)); + return res; + } - //////////////////////////////////////// + //////////////////////////////////////// - class error_id; + class error_id; - namespace leaf_detail - { - BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept; - } + namespace leaf_detail + { + BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept; + } - class error_id - { - friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept; + class error_id + { + friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept; - int value_; + int value_; - BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept: - value_(value) - { - BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1)); - } + BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept: + value_(value) + { + BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1)); + } - public: + public: - BOOST_LEAF_CONSTEXPR error_id() noexcept: - value_(0) - { - } + BOOST_LEAF_CONSTEXPR error_id() noexcept: + value_(0) + { + } - error_id( std::error_code const & ec ) noexcept: - value_(leaf_detail::import_error_code(ec)) - { - BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1)); - } + error_id( std::error_code const & ec ) noexcept: + value_(leaf_detail::import_error_code(ec)) + { + BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1)); + } - template - error_id( Enum e, typename std::enable_if::value, Enum>::type * = 0 ) noexcept: - value_(leaf_detail::import_error_code(e)) - { - } + template + error_id( Enum e, typename std::enable_if::value, Enum>::type * = 0 ) noexcept: + value_(leaf_detail::import_error_code(e)) + { + } - BOOST_LEAF_CONSTEXPR error_id load() const noexcept - { - return *this; - } + BOOST_LEAF_CONSTEXPR error_id load() const noexcept + { + return *this; + } - template - BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept - { - if( int err_id = value() ) - { - int const unused[ ] = { 42, leaf_detail::load_item::load(err_id, std::forward(item))... }; - (void) unused; - } - return *this; - } + template + BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept + { + if( int err_id = value() ) + { + int const unused[ ] = { 42, leaf_detail::load_item::load(err_id, std::forward(item))... }; + (void) unused; + } + return *this; + } - std::error_code to_error_code() const noexcept - { - return std::error_code(value_, leaf_detail::get_error_category<>::cat); - } + std::error_code to_error_code() const noexcept + { + return std::error_code(value_, leaf_detail::get_error_category<>::cat); + } - BOOST_LEAF_CONSTEXPR int value() const noexcept - { - if( int v = value_ ) - { - BOOST_LEAF_ASSERT((v&3)==1); - return (v&~3)|1; - } - else - return 0; - } + BOOST_LEAF_CONSTEXPR int value() const noexcept + { + if( int v = value_ ) + { + BOOST_LEAF_ASSERT((v&3)==1); + return (v&~3)|1; + } + else + return 0; + } - BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept - { - return value_ != 0; - } + BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept + { + return value_ != 0; + } - BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept - { - return a.value_ == b.value_; - } + BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept + { + return a.value_ == b.value_; + } - BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept - { - return !(a == b); - } + BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept + { + return !(a == b); + } - BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept - { - return a.value_ < b.value_; - } + BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept + { + return a.value_ < b.value_; + } - friend std::ostream & operator<<( std::ostream & os, error_id x ) - { - return os << x.value_; - } + friend std::ostream & operator<<( std::ostream & os, error_id x ) + { + return os << x.value_; + } - BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept - { - BOOST_LEAF_ASSERT(file&&*file); - BOOST_LEAF_ASSERT(line>0); - BOOST_LEAF_ASSERT(function&&*function); - BOOST_LEAF_ASSERT(value_); - (void) load(e_source_location {file,line,function}); - } - }; + BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept + { + BOOST_LEAF_ASSERT(file&&*file); + BOOST_LEAF_ASSERT(line>0); + BOOST_LEAF_ASSERT(function&&*function); + BOOST_LEAF_ASSERT(value_); + (void) load(e_source_location {file,line,function}); + } + }; - namespace leaf_detail - { - BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept - { - BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1); - return error_id((err_id&~3)|1); - } - } + namespace leaf_detail + { + BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept + { + BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1); + return error_id((err_id&~3)|1); + } + } - inline error_id new_error() noexcept - { - return leaf_detail::make_error_id(leaf_detail::new_id()); - } + inline error_id new_error() noexcept + { + return leaf_detail::make_error_id(leaf_detail::new_id()); + } - template - inline error_id new_error( Item && ... item ) noexcept - { - return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward(item)...); - } + template + inline error_id new_error( Item && ... item ) noexcept + { + return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward(item)...); + } - inline error_id current_error() noexcept - { - return leaf_detail::make_error_id(leaf_detail::current_id()); - } + inline error_id current_error() noexcept + { + return leaf_detail::make_error_id(leaf_detail::current_id()); + } - //////////////////////////////////////////// + //////////////////////////////////////////// - class polymorphic_context - { - protected: + class polymorphic_context + { + protected: - polymorphic_context() noexcept = default; - ~polymorphic_context() noexcept = default; + polymorphic_context() noexcept = default; + ~polymorphic_context() noexcept = default; - public: + public: - virtual error_id propagate_captured_errors() noexcept = 0; - virtual void activate() noexcept = 0; - virtual void deactivate() noexcept = 0; - virtual void propagate() noexcept = 0; - virtual bool is_active() const noexcept = 0; - virtual void print( std::ostream & ) const = 0; - error_id captured_id_; - }; + virtual error_id propagate_captured_errors() noexcept = 0; + virtual void activate() noexcept = 0; + virtual void deactivate() noexcept = 0; + virtual void propagate() noexcept = 0; + virtual bool is_active() const noexcept = 0; + virtual void print( std::ostream & ) const = 0; + error_id captured_id_; + }; - using context_ptr = std::shared_ptr; + using context_ptr = std::shared_ptr; - //////////////////////////////////////////// + //////////////////////////////////////////// - template - class context_activator - { - context_activator( context_activator const & ) = delete; - context_activator & operator=( context_activator const & ) = delete; + template + class context_activator + { + context_activator( context_activator const & ) = delete; + context_activator & operator=( context_activator const & ) = delete; #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - int const uncaught_exceptions_; + int const uncaught_exceptions_; #endif - Ctx * ctx_; + Ctx * ctx_; - public: + public: - explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept: + explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - uncaught_exceptions_(std::uncaught_exceptions()), + uncaught_exceptions_(std::uncaught_exceptions()), #endif - ctx_(ctx.is_active() ? 0 : &ctx) - { - if( ctx_ ) - ctx_->activate(); - } + ctx_(ctx.is_active() ? 0 : &ctx) + { + if( ctx_ ) + ctx_->activate(); + } - BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept: + BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - uncaught_exceptions_(x.uncaught_exceptions_), + uncaught_exceptions_(x.uncaught_exceptions_), #endif - ctx_(x.ctx_) - { - x.ctx_ = 0; - } + ctx_(x.ctx_) + { + x.ctx_ = 0; + } - BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept - { - if( !ctx_ ) - return; - if( ctx_->is_active() ) - ctx_->deactivate(); + BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept + { + if( !ctx_ ) + return; + if( ctx_->is_active() ) + ctx_->deactivate(); #ifndef BOOST_LEAF_NO_EXCEPTIONS -# if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - if( std::uncaught_exceptions() > uncaught_exceptions_ ) -# else - if( std::uncaught_exception() ) -# endif - ctx_->propagate(); +# if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + if( std::uncaught_exceptions() > uncaught_exceptions_ ) +# else + if( std::uncaught_exception() ) +# endif + ctx_->propagate(); #endif - } - }; + } + }; - template - BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator activate_context(Ctx & ctx) noexcept - { - return context_activator(ctx); - } + template + BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator activate_context(Ctx & ctx) noexcept + { + return context_activator(ctx); + } - //////////////////////////////////////////// + //////////////////////////////////////////// - template - struct is_result_type: std::false_type - { - }; + template + struct is_result_type: std::false_type + { + }; - template - struct is_result_type: is_result_type - { - }; + template + struct is_result_type: is_result_type + { + }; } } @@ -1737,22 +1737,22 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - namespace leaf_detail - { - struct throw_with_loc - { - char const * const file; - int const line; - char const * const fn; + namespace leaf_detail + { + struct throw_with_loc + { + char const * const file; + int const line; + char const * const fn; - template - [[noreturn]] friend void operator+( throw_with_loc loc, Ex const & ex ) - { - ex.load_source_location_(loc.file, loc.line, loc.fn); - ::boost::leaf::throw_exception(ex); - } - }; - } + template + [[noreturn]] friend void operator+( throw_with_loc loc, Ex const & ex ) + { + ex.load_source_location_(loc.file, loc.line, loc.fn); + ::boost::leaf::throw_exception(ex); + } + }; + } } } @@ -1760,94 +1760,94 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - namespace leaf_detail - { - inline void enforce_std_exception( std::exception const & ) noexcept { } + namespace leaf_detail + { + inline void enforce_std_exception( std::exception const & ) noexcept { } - class exception_base - { - std::shared_ptr auto_id_bump_; - public: + class exception_base + { + std::shared_ptr auto_id_bump_; + public: - virtual error_id get_error_id() const noexcept = 0; + virtual error_id get_error_id() const noexcept = 0; - protected: + protected: - exception_base(): - auto_id_bump_(0, [](void const *) { (void) new_id(); }) - { - } + exception_base(): + auto_id_bump_(0, [](void const *) { (void) new_id(); }) + { + } - ~exception_base() noexcept { } - }; + ~exception_base() noexcept { } + }; - template - class exception: - public Ex, - public exception_base, - public error_id - { - error_id get_error_id() const noexcept final override - { - return *this; - } + template + class exception: + public Ex, + public exception_base, + public error_id + { + error_id get_error_id() const noexcept final override + { + return *this; + } - public: + public: - exception( exception const & ) = default; - exception( exception && ) = default; + exception( exception const & ) = default; + exception( exception && ) = default; - BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept: - Ex(std::move(ex)), - error_id(id) - { - enforce_std_exception(*this); - } + BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept: + Ex(std::move(ex)), + error_id(id) + { + enforce_std_exception(*this); + } - explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept: - error_id(id) - { - enforce_std_exception(*this); - } - }; + explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept: + error_id(id) + { + enforce_std_exception(*this); + } + }; - template - struct at_least_one_derives_from_std_exception; + template + struct at_least_one_derives_from_std_exception; - template <> - struct at_least_one_derives_from_std_exception<>: std::false_type { }; + template <> + struct at_least_one_derives_from_std_exception<>: std::false_type { }; - template - struct at_least_one_derives_from_std_exception - { - constexpr static const bool value = std::is_base_of::value || at_least_one_derives_from_std_exception::value; - }; - } + template + struct at_least_one_derives_from_std_exception + { + constexpr static const bool value = std::is_base_of::value || at_least_one_derives_from_std_exception::value; + }; + } - template - inline - typename std::enable_if::value, leaf_detail::exception>::type - exception( Ex && ex, E && ... e ) noexcept - { - static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); - auto id = leaf::new_error(std::forward(e)...); - return leaf_detail::exception(id, std::forward(ex)); - } + template + inline + typename std::enable_if::value, leaf_detail::exception>::type + exception( Ex && ex, E && ... e ) noexcept + { + static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); + auto id = leaf::new_error(std::forward(e)...); + return leaf_detail::exception(id, std::forward(ex)); + } - template - inline - typename std::enable_if::value, leaf_detail::exception>::type - exception( E1 && car, E && ... cdr ) noexcept - { - static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); - auto id = leaf::new_error(std::forward(car), std::forward(cdr)...); - return leaf_detail::exception(id); - } + template + inline + typename std::enable_if::value, leaf_detail::exception>::type + exception( E1 && car, E && ... cdr ) noexcept + { + static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); + auto id = leaf::new_error(std::forward(car), std::forward(cdr)...); + return leaf_detail::exception(id); + } - inline leaf_detail::exception exception() noexcept - { - return leaf_detail::exception(leaf::new_error()); - } + inline leaf_detail::exception exception() noexcept + { + return leaf_detail::exception(leaf::new_error()); + } } } @@ -1865,257 +1865,257 @@ namespace boost { namespace leaf { // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif namespace boost { namespace leaf { - class error_monitor - { + class error_monitor + { #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - int const uncaught_exceptions_; + int const uncaught_exceptions_; #endif - int const err_id_; + int const err_id_; - public: + public: - error_monitor() noexcept: + error_monitor() noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - uncaught_exceptions_(std::uncaught_exceptions()), + uncaught_exceptions_(std::uncaught_exceptions()), #endif - err_id_(leaf_detail::current_id()) - { - } + err_id_(leaf_detail::current_id()) + { + } - int check_id() const noexcept - { - int err_id = leaf_detail::current_id(); - if( err_id != err_id_ ) - return err_id; - else - { + int check_id() const noexcept + { + int err_id = leaf_detail::current_id(); + if( err_id != err_id_ ) + return err_id; + else + { #ifndef BOOST_LEAF_NO_EXCEPTIONS -# if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS - if( std::uncaught_exceptions() > uncaught_exceptions_ ) -# else - if( std::uncaught_exception() ) -# endif - return leaf_detail::new_id(); +# if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS + if( std::uncaught_exceptions() > uncaught_exceptions_ ) +# else + if( std::uncaught_exception() ) +# endif + return leaf_detail::new_id(); #endif - return 0; - } - } + return 0; + } + } - int get_id() const noexcept - { - int err_id = leaf_detail::current_id(); - if( err_id != err_id_ ) - return err_id; - else - return leaf_detail::new_id(); - } + int get_id() const noexcept + { + int err_id = leaf_detail::current_id(); + if( err_id != err_id_ ) + return err_id; + else + return leaf_detail::new_id(); + } - error_id check() const noexcept - { - return leaf_detail::make_error_id(check_id()); - } + error_id check() const noexcept + { + return leaf_detail::make_error_id(check_id()); + } - error_id assigned_error_id() const noexcept - { - return leaf_detail::make_error_id(get_id()); - } - }; + error_id assigned_error_id() const noexcept + { + return leaf_detail::make_error_id(get_id()); + } + }; - //////////////////////////////////////////// + //////////////////////////////////////////// - namespace leaf_detail - { - template - struct tuple_for_each_preload - { - BOOST_LEAF_CONSTEXPR static void trigger( Tuple & tup, int err_id ) noexcept - { - BOOST_LEAF_ASSERT((err_id&3)==1); - tuple_for_each_preload::trigger(tup,err_id); - std::get(tup).trigger(err_id); - } - }; + namespace leaf_detail + { + template + struct tuple_for_each_preload + { + BOOST_LEAF_CONSTEXPR static void trigger( Tuple & tup, int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + tuple_for_each_preload::trigger(tup,err_id); + std::get(tup).trigger(err_id); + } + }; - template - struct tuple_for_each_preload<0, Tuple> - { - BOOST_LEAF_CONSTEXPR static void trigger( Tuple const &, int ) noexcept { } - }; + template + struct tuple_for_each_preload<0, Tuple> + { + BOOST_LEAF_CONSTEXPR static void trigger( Tuple const &, int ) noexcept { } + }; - template - class preloaded_item - { - using decay_E = typename std::decay::type; - slot * s_; - decay_E e_; + template + class preloaded_item + { + using decay_E = typename std::decay::type; + slot * s_; + decay_E e_; - public: + public: - BOOST_LEAF_CONSTEXPR preloaded_item( E && e ): - s_(tl_slot_ptr::p), - e_(std::forward(e)) - { - } + BOOST_LEAF_CONSTEXPR preloaded_item( E && e ): + s_(tl_slot_ptr::p), + e_(std::forward(e)) + { + } - BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept - { - BOOST_LEAF_ASSERT((err_id&3)==1); - if( s_ ) - { - if( !s_->has_value(err_id) ) - s_->put(err_id, std::move(e_)); - } + BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + if( s_ ) + { + if( !s_->has_value(err_id) ) + s_->put(err_id, std::move(e_)); + } #if BOOST_LEAF_DIAGNOSTICS - else - { - int c = tl_unexpected_enabled<>::counter; - BOOST_LEAF_ASSERT(c>=0); - if( c ) - load_unexpected(err_id, std::move(e_)); - } + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + load_unexpected(err_id, std::move(e_)); + } #endif - } - }; + } + }; - template - class deferred_item - { - using E = decltype(std::declval()()); - slot * s_; - F f_; + template + class deferred_item + { + using E = decltype(std::declval()()); + slot * s_; + F f_; - public: + public: - BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept: - s_(tl_slot_ptr::p), - f_(std::forward(f)) - { - } + BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept: + s_(tl_slot_ptr::p), + f_(std::forward(f)) + { + } - BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept - { - BOOST_LEAF_ASSERT((err_id&3)==1); - if( s_ ) - { - if( !s_->has_value(err_id) ) - s_->put(err_id, f_()); - } + BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + if( s_ ) + { + if( !s_->has_value(err_id) ) + s_->put(err_id, f_()); + } #if BOOST_LEAF_DIAGNOSTICS - else - { - int c = tl_unexpected_enabled<>::counter; - BOOST_LEAF_ASSERT(c>=0); - if( c ) - load_unexpected(err_id, std::forward(f_())); - } + else + { + int c = tl_unexpected_enabled<>::counter; + BOOST_LEAF_ASSERT(c>=0); + if( c ) + load_unexpected(err_id, std::forward(f_())); + } #endif - } - }; + } + }; - template , int arity = function_traits::arity> - class accumulating_item; + template , int arity = function_traits::arity> + class accumulating_item; - template - class accumulating_item - { - using E = A0; - slot * s_; - F f_; + template + class accumulating_item + { + using E = A0; + slot * s_; + F f_; - public: + public: - BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept: - s_(tl_slot_ptr::p), - f_(std::forward(f)) - { - } + BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept: + s_(tl_slot_ptr::p), + f_(std::forward(f)) + { + } - BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept - { - BOOST_LEAF_ASSERT((err_id&3)==1); - if( s_ ) - if( E * e = s_->has_value(err_id) ) - (void) f_(*e); - else - (void) f_(s_->put(err_id, E())); - } - }; + BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept + { + BOOST_LEAF_ASSERT((err_id&3)==1); + if( s_ ) + if( E * e = s_->has_value(err_id) ) + (void) f_(*e); + else + (void) f_(s_->put(err_id, E())); + } + }; - template - class preloaded - { - preloaded & operator=( preloaded const & ) = delete; + template + class preloaded + { + preloaded & operator=( preloaded const & ) = delete; - std::tuple p_; - bool moved_; - error_monitor id_; + std::tuple p_; + bool moved_; + error_monitor id_; - public: + public: - BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ): - p_(std::forward(i)...), - moved_(false) - { - } + BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ): + p_(std::forward(i)...), + moved_(false) + { + } - BOOST_LEAF_CONSTEXPR preloaded( preloaded && x ) noexcept: - p_(std::move(x.p_)), - moved_(false), - id_(std::move(x.id_)) - { - x.moved_ = true; - } + BOOST_LEAF_CONSTEXPR preloaded( preloaded && x ) noexcept: + p_(std::move(x.p_)), + moved_(false), + id_(std::move(x.id_)) + { + x.moved_ = true; + } - ~preloaded() noexcept - { - if( moved_ ) - return; - if( auto id = id_.check_id() ) - tuple_for_each_preload::trigger(p_,id); - } - }; + ~preloaded() noexcept + { + if( moved_ ) + return; + if( auto id = id_.check_id() ) + tuple_for_each_preload::trigger(p_,id); + } + }; - template ::arity> - struct deduce_item_type; + template ::arity> + struct deduce_item_type; - template - struct deduce_item_type - { - using type = preloaded_item; - }; + template + struct deduce_item_type + { + using type = preloaded_item; + }; - template - struct deduce_item_type - { - using type = deferred_item; - }; + template + struct deduce_item_type + { + using type = deferred_item; + }; - template - struct deduce_item_type - { - using type = accumulating_item; - }; - } + template + struct deduce_item_type + { + using type = accumulating_item; + }; + } - template - BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline - leaf_detail::preloaded::type...> - on_error( Item && ... i ) - { - return leaf_detail::preloaded::type...>(std::forward(i)...); - } + template + BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline + leaf_detail::preloaded::type...> + on_error( Item && ... i ) + { + return leaf_detail::preloaded::type...>(std::forward(i)...); + } } } @@ -2126,276 +2126,276 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - namespace leaf_detail - { - template ::value> - struct is_result_tag; + namespace leaf_detail + { + template ::value> + struct is_result_tag; - template - struct is_result_tag - { - }; + template + struct is_result_tag + { + }; - template - struct is_result_tag - { - }; - } + template + struct is_result_tag + { + }; + } #ifdef BOOST_LEAF_NO_EXCEPTIONS - namespace leaf_detail - { - template - inline - decltype(std::declval()(std::forward(std::declval())...)) - capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept - { - auto active_context = activate_context(*ctx); - return std::forward(f)(std::forward(a)...); - } + namespace leaf_detail + { + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept + { + auto active_context = activate_context(*ctx); + return std::forward(f)(std::forward(a)...); + } - template - inline - decltype(std::declval()(std::forward(std::declval())...)) - capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept - { - auto active_context = activate_context(*ctx); - if( auto r = std::forward(f)(std::forward(a)...) ) - return r; - else - { - ctx->captured_id_ = r.error(); - return std::move(ctx); - } - } + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept + { + auto active_context = activate_context(*ctx); + if( auto r = std::forward(f)(std::forward(a)...) ) + return r; + else + { + ctx->captured_id_ = r.error(); + return std::move(ctx); + } + } - template - inline - decltype(std::declval().get()) - future_get_impl(is_result_tag, Future & fut) noexcept - { - return fut.get(); - } + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut) noexcept + { + return fut.get(); + } - template - inline - decltype(std::declval().get()) - future_get_impl(is_result_tag, Future & fut) noexcept - { - if( auto r = fut.get() ) - return r; - else - return error_id(r.error()); // unloads - } - } + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut) noexcept + { + if( auto r = fut.get() ) + return r; + else + return error_id(r.error()); // unloads + } + } #else - namespace leaf_detail - { - class capturing_exception: - public std::exception - { - std::exception_ptr ex_; - context_ptr ctx_; + namespace leaf_detail + { + class capturing_exception: + public std::exception + { + std::exception_ptr ex_; + context_ptr ctx_; - public: + public: - capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept: - ex_(std::move(ex)), - ctx_(std::move(ctx)) - { - BOOST_LEAF_ASSERT(ex_); - BOOST_LEAF_ASSERT(ctx_); - BOOST_LEAF_ASSERT(ctx_->captured_id_); - } + capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept: + ex_(std::move(ex)), + ctx_(std::move(ctx)) + { + BOOST_LEAF_ASSERT(ex_); + BOOST_LEAF_ASSERT(ctx_); + BOOST_LEAF_ASSERT(ctx_->captured_id_); + } - [[noreturn]] void unload_and_rethrow_original_exception() const - { - BOOST_LEAF_ASSERT(ctx_->captured_id_); - auto active_context = activate_context(*ctx_); - id_factory<>::current_id = ctx_->captured_id_.value(); - std::rethrow_exception(ex_); - } + [[noreturn]] void unload_and_rethrow_original_exception() const + { + BOOST_LEAF_ASSERT(ctx_->captured_id_); + auto active_context = activate_context(*ctx_); + id_factory<>::current_id = ctx_->captured_id_.value(); + std::rethrow_exception(ex_); + } - void print( std::ostream & os ) const - { - ctx_->print(os); - } - }; + void print( std::ostream & os ) const + { + ctx_->print(os); + } + }; - template - inline - decltype(std::declval()(std::forward(std::declval())...)) - capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) - { - auto active_context = activate_context(*ctx); - error_monitor cur_err; - try - { - return std::forward(f)(std::forward(a)...); - } - catch( capturing_exception const & ) - { - throw; - } - catch( exception_base const & e ) - { - ctx->captured_id_ = e.get_error_id(); - throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); - } - catch(...) - { - ctx->captured_id_ = cur_err.assigned_error_id(); - throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); - } - } + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) + { + auto active_context = activate_context(*ctx); + error_monitor cur_err; + try + { + return std::forward(f)(std::forward(a)...); + } + catch( capturing_exception const & ) + { + throw; + } + catch( exception_base const & e ) + { + ctx->captured_id_ = e.get_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + catch(...) + { + ctx->captured_id_ = cur_err.assigned_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + } - template - inline - decltype(std::declval()(std::forward(std::declval())...)) - capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) - { - auto active_context = activate_context(*ctx); - error_monitor cur_err; - try - { - if( auto && r = std::forward(f)(std::forward(a)...) ) - return std::move(r); - else - { - ctx->captured_id_ = r.error(); - return std::move(ctx); - } - } - catch( capturing_exception const & ) - { - throw; - } - catch( exception_base const & e ) - { - ctx->captured_id_ = e.get_error_id(); - throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); - } - catch(...) - { - ctx->captured_id_ = cur_err.assigned_error_id(); - throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); - } - } + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) + { + auto active_context = activate_context(*ctx); + error_monitor cur_err; + try + { + if( auto && r = std::forward(f)(std::forward(a)...) ) + return std::move(r); + else + { + ctx->captured_id_ = r.error(); + return std::move(ctx); + } + } + catch( capturing_exception const & ) + { + throw; + } + catch( exception_base const & e ) + { + ctx->captured_id_ = e.get_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + catch(...) + { + ctx->captured_id_ = cur_err.assigned_error_id(); + throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); + } + } - template - inline - decltype(std::declval().get()) - future_get_impl(is_result_tag, Future & fut ) - { - try - { - return fut.get(); - } - catch( capturing_exception const & cap ) - { - cap.unload_and_rethrow_original_exception(); - } - } + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut ) + { + try + { + return fut.get(); + } + catch( capturing_exception const & cap ) + { + cap.unload_and_rethrow_original_exception(); + } + } - template - inline - decltype(std::declval().get()) - future_get_impl(is_result_tag, Future & fut ) - { - try - { - if( auto r = fut.get() ) - return r; - else - return error_id(r.error()); // unloads - } - catch( capturing_exception const & cap ) - { - cap.unload_and_rethrow_original_exception(); - } - } - } + template + inline + decltype(std::declval().get()) + future_get_impl(is_result_tag, Future & fut ) + { + try + { + if( auto r = fut.get() ) + return r; + else + return error_id(r.error()); // unloads + } + catch( capturing_exception const & cap ) + { + cap.unload_and_rethrow_original_exception(); + } + } + } #endif - template - inline - decltype(std::declval()(std::forward(std::declval())...)) - capture(context_ptr && ctx, F && f, A... a) - { - using namespace leaf_detail; - return capture_impl(is_result_tag()(std::forward(std::declval())...))>(), std::move(ctx), std::forward(f), std::forward(a)...); - } + template + inline + decltype(std::declval()(std::forward(std::declval())...)) + capture(context_ptr && ctx, F && f, A... a) + { + using namespace leaf_detail; + return capture_impl(is_result_tag()(std::forward(std::declval())...))>(), std::move(ctx), std::forward(f), std::forward(a)...); + } - template - inline - decltype(std::declval().get()) - future_get( Future & fut ) - { - using namespace leaf_detail; - return future_get_impl(is_result_tag().get())>(), fut); - } + template + inline + decltype(std::declval().get()) + future_get( Future & fut ) + { + using namespace leaf_detail; + return future_get_impl(is_result_tag().get())>(), fut); + } - //////////////////////////////////////// + //////////////////////////////////////// #ifndef BOOST_LEAF_NO_EXCEPTIONS - template - class result; + template + class result; - namespace leaf_detail - { - inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<> ) - { - return leaf::new_error(std::current_exception()); - } + namespace leaf_detail + { + inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<> ) + { + return leaf::new_error(std::current_exception()); + } - template - inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list ) - { - if( Ex1 const * p = dynamic_cast(&ex) ) - return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }).load(*p); - else - return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }); - } + template + inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list ) + { + if( Ex1 const * p = dynamic_cast(&ex) ) + return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }).load(*p); + else + return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }); + } - template - struct deduce_exception_to_result_return_type_impl - { - using type = result; - }; + template + struct deduce_exception_to_result_return_type_impl + { + using type = result; + }; - template - struct deduce_exception_to_result_return_type_impl> - { - using type = result; - }; + template + struct deduce_exception_to_result_return_type_impl> + { + using type = result; + }; - template - using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl::type; - } + template + using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl::type; + } - template - inline - leaf_detail::deduce_exception_to_result_return_type> - exception_to_result( F && f ) noexcept - { - try - { - return std::forward(f)(); - } - catch( std::exception const & ex ) - { - return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list()); - } - catch(...) - { - return leaf::new_error(std::current_exception()); - } - } + template + inline + leaf_detail::deduce_exception_to_result_return_type> + exception_to_result( F && f ) noexcept + { + try + { + return std::forward(f)(); + } + catch( std::exception const & ex ) + { + return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list()); + } + catch(...) + { + return leaf::new_error(std::current_exception()); + } + } #endif @@ -2415,88 +2415,88 @@ namespace boost { namespace leaf { // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif #include #include #ifdef _WIN32 -# include -# include +# include +# include #ifdef min -# undef min +# undef min #endif #ifdef max -# undef max +# undef max #endif #endif namespace boost { namespace leaf { - struct e_api_function { char const * value; }; + struct e_api_function { char const * value; }; - struct e_file_name { std::string value; }; + struct e_file_name { std::string value; }; - struct e_errno - { - int value; + struct e_errno + { + int value; - friend std::ostream & operator<<( std::ostream & os, e_errno const & err ) - { - return os << type() << ": " << err.value << ", \"" << std::strerror(err.value) << '"'; - } - }; + friend std::ostream & operator<<( std::ostream & os, e_errno const & err ) + { + return os << type() << ": " << err.value << ", \"" << std::strerror(err.value) << '"'; + } + }; - struct e_type_info_name { char const * value; }; + struct e_type_info_name { char const * value; }; - struct e_at_line { int value; }; + struct e_at_line { int value; }; - namespace windows - { - struct e_LastError - { - unsigned value; + namespace windows + { + struct e_LastError + { + unsigned value; #ifdef _WIN32 - friend std::ostream & operator<<( std::ostream & os, e_LastError const & err ) - { - struct msg_buf - { - LPVOID * p; - msg_buf(): p(0) { } - ~msg_buf() noexcept { if(p) LocalFree(p); } - }; - msg_buf mb; - if( FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - 0, - err.value, - MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), - (LPSTR)&mb.p, - 0, - 0) ) - { - BOOST_LEAF_ASSERT(mb.p != 0); - char * z = std::strchr((LPSTR)mb.p,0); - if( z[-1] == '\n' ) - *--z = 0; - if( z[-1] == '\r' ) - *--z = 0; - return os << type() << ": " << err.value << ", \"" << (LPCSTR)mb.p << '"'; - } - return os; - } + friend std::ostream & operator<<( std::ostream & os, e_LastError const & err ) + { + struct msg_buf + { + LPVOID * p; + msg_buf(): p(0) { } + ~msg_buf() noexcept { if(p) LocalFree(p); } + }; + msg_buf mb; + if( FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + 0, + err.value, + MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + (LPSTR)&mb.p, + 0, + 0) ) + { + BOOST_LEAF_ASSERT(mb.p != 0); + char * z = std::strchr((LPSTR)mb.p,0); + if( z[-1] == '\n' ) + *--z = 0; + if( z[-1] == '\r' ) + *--z = 0; + return os << type() << ": " << err.value << ", \"" << (LPCSTR)mb.p << '"'; + } + return os; + } #else - // TODO : Other platforms + // TODO : Other platforms #endif - }; - } + }; + } } } @@ -2514,453 +2514,453 @@ namespace boost { namespace leaf { // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS -# if defined(__clang__) -# pragma clang system_header -# elif (__GNUC__*100+__GNUC_MINOR__>301) -# pragma GCC system_header -# elif defined(_MSC_VER) -# pragma warning(push,1) -# endif +# if defined(__clang__) +# pragma clang system_header +# elif (__GNUC__*100+__GNUC_MINOR__>301) +# pragma GCC system_header +# elif defined(_MSC_VER) +# pragma warning(push,1) +# endif #endif namespace boost { namespace leaf { - class error_info; - class diagnostic_info; - class verbose_diagnostic_info; + class error_info; + class diagnostic_info; + class verbose_diagnostic_info; - template - struct is_predicate: std::false_type - { - }; + template + struct is_predicate: std::false_type + { + }; - namespace leaf_detail - { - template - struct is_exception: std::is_base_of::type> - { - }; + namespace leaf_detail + { + template + struct is_exception: std::is_base_of::type> + { + }; - template - struct handler_argument_traits; + template + struct handler_argument_traits; - template ::value> - struct handler_argument_traits_defaults; + template ::value> + struct handler_argument_traits_defaults; - template - struct handler_argument_traits_defaults - { - using error_type = typename std::decay::type; - constexpr static bool always_available = false; + template + struct handler_argument_traits_defaults + { + using error_type = typename std::decay::type; + constexpr static bool always_available = false; - template - BOOST_LEAF_CONSTEXPR static error_type const * check( Tup const &, error_info const & ) noexcept; + template + BOOST_LEAF_CONSTEXPR static error_type const * check( Tup const &, error_info const & ) noexcept; - template - BOOST_LEAF_CONSTEXPR static error_type * check( Tup &, error_info const & ) noexcept; + template + BOOST_LEAF_CONSTEXPR static error_type * check( Tup &, error_info const & ) noexcept; - template - BOOST_LEAF_CONSTEXPR static E get( Tup & tup, error_info const & ei ) noexcept - { - return *check(tup, ei); - } + template + BOOST_LEAF_CONSTEXPR static E get( Tup & tup, error_info const & ei ) noexcept + { + return *check(tup, ei); + } - static_assert(!is_predicate::value, "Handlers must take predicate arguments by value"); - static_assert(!std::is_same::value, "Handlers must take leaf::error_info arguments by const &"); - static_assert(!std::is_same::value, "Handlers must take leaf::diagnostic_info arguments by const &"); - static_assert(!std::is_same::value, "Handlers must take leaf::verbose_diagnostic_info arguments by const &"); - }; + static_assert(!is_predicate::value, "Handlers must take predicate arguments by value"); + static_assert(!std::is_same::value, "Handlers must take leaf::error_info arguments by const &"); + static_assert(!std::is_same::value, "Handlers must take leaf::diagnostic_info arguments by const &"); + static_assert(!std::is_same::value, "Handlers must take leaf::verbose_diagnostic_info arguments by const &"); + }; - template - struct handler_argument_traits_defaults: handler_argument_traits - { - using base = handler_argument_traits; - static_assert(!base::always_available, "Predicates can't use types that are always_available"); + template + struct handler_argument_traits_defaults: handler_argument_traits + { + using base = handler_argument_traits; + static_assert(!base::always_available, "Predicates can't use types that are always_available"); - template - BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept - { - auto e = base::check(tup, ei); - return e && Pred::evaluate(*e); - }; + template + BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept + { + auto e = base::check(tup, ei); + return e && Pred::evaluate(*e); + }; - template - BOOST_LEAF_CONSTEXPR static Pred get( Tup const & tup, error_info const & ei ) noexcept - { - return Pred{*base::check(tup, ei)}; - } - }; + template + BOOST_LEAF_CONSTEXPR static Pred get( Tup const & tup, error_info const & ei ) noexcept + { + return Pred{*base::check(tup, ei)}; + } + }; - template - struct handler_argument_always_available - { - using error_type = E; - constexpr static bool always_available = true; + template + struct handler_argument_always_available + { + using error_type = E; + constexpr static bool always_available = true; - template - BOOST_LEAF_CONSTEXPR static bool check( Tup &, error_info const & ) noexcept - { - return true; - }; - }; + template + BOOST_LEAF_CONSTEXPR static bool check( Tup &, error_info const & ) noexcept + { + return true; + }; + }; - template - struct handler_argument_traits: handler_argument_traits_defaults - { - }; + template + struct handler_argument_traits: handler_argument_traits_defaults + { + }; - template <> - struct handler_argument_traits - { - using error_type = void; - constexpr static bool always_available = false; + template <> + struct handler_argument_traits + { + using error_type = void; + constexpr static bool always_available = false; - template - BOOST_LEAF_CONSTEXPR static std::exception const * check( Tup const &, error_info const & ) noexcept; - }; + template + BOOST_LEAF_CONSTEXPR static std::exception const * check( Tup const &, error_info const & ) noexcept; + }; - template - struct handler_argument_traits - { - static_assert(sizeof(E) == 0, "Error handlers may not take rvalue ref arguments"); - }; + template + struct handler_argument_traits + { + static_assert(sizeof(E) == 0, "Error handlers may not take rvalue ref arguments"); + }; - template - struct handler_argument_traits: handler_argument_always_available::type> - { - template - BOOST_LEAF_CONSTEXPR static E * get( Tup & tup, error_info const & ei) noexcept - { - return handler_argument_traits_defaults::check(tup, ei); - } - }; + template + struct handler_argument_traits: handler_argument_always_available::type> + { + template + BOOST_LEAF_CONSTEXPR static E * get( Tup & tup, error_info const & ei) noexcept + { + return handler_argument_traits_defaults::check(tup, ei); + } + }; - template <> - struct handler_argument_traits: handler_argument_always_available - { - template - BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept - { - return ei; - } - }; + template <> + struct handler_argument_traits: handler_argument_always_available + { + template + BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept + { + return ei; + } + }; - template - struct handler_argument_traits_require_by_value - { - static_assert(sizeof(E) == 0, "Error handlers must take this type by value"); - }; - } + template + struct handler_argument_traits_require_by_value + { + static_assert(sizeof(E) == 0, "Error handlers must take this type by value"); + }; + } - //////////////////////////////////////// + //////////////////////////////////////// - namespace leaf_detail - { - template - struct tuple_for_each - { - BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept - { - static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); - tuple_for_each::activate(tup); - std::get(tup).activate(); - } + namespace leaf_detail + { + template + struct tuple_for_each + { + BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + tuple_for_each::activate(tup); + std::get(tup).activate(); + } - BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept - { - static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); - std::get(tup).deactivate(); - tuple_for_each::deactivate(tup); - } + BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + std::get(tup).deactivate(); + tuple_for_each::deactivate(tup); + } - BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept - { - static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); - auto & sl = std::get(tup); - sl.propagate(); - tuple_for_each::propagate(tup); - } + BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + auto & sl = std::get(tup); + sl.propagate(); + tuple_for_each::propagate(tup); + } - BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept - { - static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); - auto & sl = std::get(tup); - if( sl.has_value(err_id) ) - load_slot(err_id, std::move(sl).value(err_id)); - tuple_for_each::propagate_captured(tup, err_id); - } + BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept + { + static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); + auto & sl = std::get(tup); + if( sl.has_value(err_id) ) + load_slot(err_id, std::move(sl).value(err_id)); + tuple_for_each::propagate_captured(tup, err_id); + } - static void print( std::ostream & os, void const * tup, int key_to_print ) - { - BOOST_LEAF_ASSERT(tup != 0); - tuple_for_each::print(os, tup, key_to_print); - std::get(*static_cast(tup)).print(os, key_to_print); - } - }; + static void print( std::ostream & os, void const * tup, int key_to_print ) + { + BOOST_LEAF_ASSERT(tup != 0); + tuple_for_each::print(os, tup, key_to_print); + std::get(*static_cast(tup)).print(os, key_to_print); + } + }; - template - struct tuple_for_each<0, Tuple> - { - BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { } - BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { } - BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { } - BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { } - static void print( std::ostream &, void const *, int ) { } - }; - } + template + struct tuple_for_each<0, Tuple> + { + BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { } + BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { } + BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { } + BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { } + static void print( std::ostream &, void const *, int ) { } + }; + } - //////////////////////////////////////////// + //////////////////////////////////////////// #if BOOST_LEAF_DIAGNOSTICS - namespace leaf_detail - { - template struct requires_unexpected { constexpr static bool value = false; }; - template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; - template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; - template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; - template <> struct requires_unexpected { constexpr static bool value = true; }; - template <> struct requires_unexpected { constexpr static bool value = true; }; + namespace leaf_detail + { + template struct requires_unexpected { constexpr static bool value = false; }; + template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; + template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; + template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; + template <> struct requires_unexpected { constexpr static bool value = true; }; + template <> struct requires_unexpected { constexpr static bool value = true; }; - template - struct unexpected_requested; + template + struct unexpected_requested; - template