The Application

The application is of course also based on Outcome, and like the HTTP library is also of mixed-failure design in that failure can be returned via error code, type erased exception_ptr or indeed a C++ exception throw.

// This is the namespace of the application which is connecting together the httplib,
// filelib and tidylib libraries into a solution.
namespace app
{
  // Create an ADL bridge so copy/move hooks will be searched for in this namespace
  struct error_code : public std::error_code
  {
    // passthrough
    using std::error_code::error_code;
    error_code() = default;
    error_code(std::error_code ec)
        : std::error_code(ec)
    {
    }
  };
  // Localise an outcome implementation for this namespace
  template <class T>
  using outcome =  //
  OUTCOME_V2_NAMESPACE::outcome<T, error_code /*, std::exception_ptr */>;
  using OUTCOME_V2_NAMESPACE::success;
}  // namespace app
View this code on Github

Here we localise a passthrough error_code solely for the purpose of ADL bridging, otherwise the localised outcome configured is the default one which comes with Outcome. We covered this technique of “passthrough error_code” earlier in this tutorial.

The way we are going to configure interop is as follows:

  1. The application shall use error_code for anticipated failure and C++ exception throws for unanticipated failure.
  2. We shall choose the convention that app::outcome with exception ptr solely and exclusively represents a type erased failure from a third party library.

Thus if one calls .value() on an app::outcome, both anticipated failure within the app and type erased failure from a third party library shall be converted to a C++ exception throw.