You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.5 KiB
130 lines
3.5 KiB
// leaf_on_error_example.cpp |
|
#include <boost/leaf.hpp> |
|
#include <ctime> |
|
#include <iostream> |
|
#include <string> |
|
#include <utility> |
|
|
|
namespace leaf = boost::leaf; |
|
|
|
struct error_tag {}; |
|
struct open_error {}; |
|
struct write_error {}; |
|
|
|
struct file_context { |
|
std::string path; |
|
}; |
|
|
|
struct user_context { |
|
std::string name; |
|
int privileges; |
|
}; |
|
|
|
struct chunk_context { |
|
int chunk; |
|
std::size_t size; |
|
std::time_t timestamp; |
|
}; |
|
|
|
leaf::result<void> write_chunk(int chunk, std::size_t size) |
|
{ |
|
chunk_context cc{chunk, size, std::time(nullptr)}; |
|
// Registers cc to be captured only if an error unwinds this scope. |
|
// On success the registration is discarded. |
|
[[maybe_unused]] auto ctx = leaf::on_error(cc); |
|
|
|
if (chunk == 3) |
|
// The context registered above rides along with this error |
|
// even though handlers live several frames up. |
|
return leaf::new_error(write_error{}); |
|
|
|
return {}; |
|
} |
|
|
|
leaf::result<void> process_file(std::string path, std::string user) |
|
{ |
|
error_tag tag; |
|
file_context fc{std::move(path)}; |
|
user_context uc{std::move(user), 0600}; |
|
|
|
[[maybe_unused]] auto tag_ctx = leaf::on_error(tag); |
|
[[maybe_unused]] auto file_ctx = leaf::on_error(fc); |
|
[[maybe_unused]] auto user_ctx = leaf::on_error(uc); |
|
|
|
// write_chunk knows nothing about the contexts registered here; |
|
// LEAF attaches them automatically to any error it propagates. |
|
for (int i = 0; i != 5; ++i) { |
|
auto r = write_chunk(i, 4096); |
|
if (!r) |
|
return r; |
|
} |
|
|
|
return {}; |
|
} |
|
|
|
int main() |
|
{ |
|
return leaf::try_handle_all( |
|
[]() -> leaf::result<int> { |
|
// Try block and handlers must return the same type. |
|
BOOST_LEAF_CHECK(process_file("data.bin", "alice")); |
|
return 0; |
|
}, |
|
|
|
// A handler runs only if the error carries every type it |
|
// requests; handlers below with fewer parameters match the |
|
// same errors when richer contexts were never registered. |
|
[](write_error const&, |
|
error_tag const&, |
|
file_context const& f, |
|
user_context const& u, |
|
chunk_context const& c) { |
|
std::cerr << "write failed: " |
|
<< "file=" << f.path |
|
<< ", user=" << u.name |
|
<< ", chunk=" << c.chunk |
|
<< ", size=" << c.size |
|
<< ", time=" << c.timestamp |
|
<< '\n'; |
|
return 1; |
|
}, |
|
|
|
[](open_error const&, |
|
error_tag const&, |
|
file_context const& f, |
|
user_context const& u) { |
|
std::cerr << "open failed: " |
|
<< "file=" << f.path |
|
<< ", user=" << u.name |
|
<< '\n'; |
|
return 2; |
|
}, |
|
|
|
[](error_tag const&, |
|
file_context const& f, |
|
user_context const& u, |
|
chunk_context const& c) { |
|
std::cerr << "unknown error: " |
|
<< "file=" << f.path |
|
<< ", user=" << u.name |
|
<< ", chunk=" << c.chunk |
|
<< '\n'; |
|
return 3; |
|
}, |
|
|
|
[](error_tag const&, |
|
file_context const& f, |
|
user_context const& u) { |
|
std::cerr << "unknown error: " |
|
<< "file=" << f.path |
|
<< ", user=" << u.name |
|
<< '\n'; |
|
return 4; |
|
}, |
|
|
|
[] { |
|
std::cerr << "unknown error before file context\n"; |
|
return 5; |
|
} |
|
); |
|
}
|
|
|