diff --git a/README.md b/README.md index 261fff0..072ddd0 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,61 @@ # expected -Single header, work-in-progress implementation of `std::expected` with functional-style extensions. +Single header implementation of `std::expected` with functional-style extensions. Clang + GCC: [![Linux Build Status](https://travis-ci.org/TartanLlama/expected.png?branch=master)](https://travis-ci.org/TartanLlama/expected) MSVC: [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k5x00xa11y3s5wsg?svg=true)](https://ci.appveyor.com/project/TartanLlama/expected) +[`std::expected`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf) is proposed as the preferred way to represent object which will either have an expected value, or an unexpected value giving information about why something failed. Unfortunately, chaining together many computations which may fail can be verbose, as error-checking code will be mixed in with the actual programming logic. This implementation provides a number of utilities to make coding with `expected` cleaner. + +For example, instead of writing this code: + +``` +std::expected get_cute_cat (const image& img) { + auto cropped = crop_to_cat(img); + if (!cropped) { + return cropped; + } + + auto with_tie = add_bow_tie(*cropped); + if (!with_tie) { + return with_tie; + } + + auto with_sparkles = make_eyes_sparkle(*with_tie); + if (!with_sparkles) { + return with_sparkles; + } + + return add_rainbow(make_smaller(*with_sparkles)); +} +``` + +You can do this: + +``` +tl::expected get_cute_cat (const image& img) { + return crop_to_cat(img) + .and_then(add_bow_tie) + .and_then(make_eyes_sparkle) + .map(make_smaller) + .map(add_rainbow); +} +``` + Full documentation available at [expected.tartanllama.xyz](https://expected.tartanllama.xyz) +The interface is the same as `std::expected` as proposed in [p0323r3](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf), but the following member functions are also defined. Explicit types are for clarity. + +- `map`: carries out some operation on the stored object if there is one. + * `tl::expected s = exp_string.map(&std::string::size);` +- `map_error`: carries out some operation on the unexpected object if there is one. + * `my_error_code translate_error (std::error_code);` + * `tl::expected s = exp_int.map(translate_error);` +- `and_then`: like `map`, but for operations which return a `tl::expected`. + * `tl::expected parse (const std::string& s);` + * `tl::expected exp_ast = exp_string.and_then(parse);` +- `or_else`: calls some function if there is no value stored. + * `exp.or_else([] { throw std::runtime_error{"oh no"}; });` + ### Compiler support Tested on: