In use - Boost.Outcome documentation

# In use

This is how you might now write application code using these three libraries:

    namespace app
    {
      // A markup function to indicate when we are ValueOrError converting
      template <class T> inline outcome<typename T::value_type> ext(T &&v)
      {  //
        return outcome<typename T::value_type>(std::move(v));
      }

      outcome<void> go()  // NOT noexcept, this can throw STL exceptions e.g. bad_alloc
      {
        // Note that explicit construction is required when converting between differing types
        // of outcome and result. This makes it explicit what you intend to do as conversion
        // may be a lot more expensive than moves.

        // Try to GET this URL. If an unsuccessful HTTP status is returned, serialise a string
        // containing a description of the HTTP status code and the URL which failed, storing
        // that into a httplib_error exception type which is stored as an exception ptr. The
        // TRY operation below will return that exception ptr to be rethrown in the caller.
        // Otherwise the fetched data is returned in a std::string data.
        BOOST_OUTCOME_TRY(auto data, ext(httplib::get("http://www.nedproductions.biz/")));
        string_view data_view(data);

        // HTML tidy the fetched data. If the C library fails due to an error corresponding to
        // a standard library exception type, throw that. Otherwise, synthesise an exception
        // ptr of type tidylib_error which stores the error code returned in an error code with
        // generic category (i.e. errno domain).
        // TRY operation below will return that exception ptr to be rethrown in the caller.
        // Otherwise the tidied data is returned into holdmem, with the string view updated to
        // point at the tidied data.
        BOOST_OUTCOME_TRY(auto holdmem, ext(tidy_html(data_view)));

        // Write the tidied data to some file. If the write fails, synthesise a filesystem_error
        // exception ptr exactly as if one called filelib::write_file(data_view).value().
        BOOST_OUTCOME_TRY(auto written, ext(filelib::write_file(data_view)));
        return success();
      }
    }  // namespace app

View this code on Github

The curiosity will be surely the `ext()` markup function, which needs explaining. It was felt important during Outcome’s design that `value_or_error` conversions never be implicit, as they almost always represent a transition across an ABI or semantic boundary. They are also usually non-trivial to implement and compile, and it was felt important that the programmer ought to always mark the semantic boundary transition at the point of every use, as considerable amounts of code may execute.

How the end user chooses to mark up their code is up to them, however above we use a simple `ext()` function to mark up that the function being called is external to the application. This ticks our box of requiring the documentation, at the point of use, of every transition in failure handling boundaries.

Note that we are able to use `TRY` as normal throughout this function. Everything “just works”.

And most especially note that we never, at any stage, needed to modify the source code of `httplib`, `tidylib` nor `filelib`, nor inject custom things into their namespaces. This entire worked example was achieved solely by `app` based customisation points, and via `convert`.

Last revised: December 15, 2020 at 12:22:39 UTC