Redefining message()

You may remember that our custom _file_io_error_domain inherits from outcome_e::posix_code::domain_type, and thus does not have to implement the many pure virtual functions required by outcome_e::status_code_domain.

What we do need to do is reimplement _do_message() to append the file and line information to the POSIX error description string returned by outcome_e::posix_code::domain_type. This causes the status code’s .message() observer to return a string with the extra payload information represented in text.

  // Return a string describing a specific code. We will return the
  // string returned by our POSIX code base domain, with the source
  // file and line number appended
  virtual _base::string_ref _do_message(const outcome_e::status_code<void> &code) const noexcept override final  // NOLINT
    assert(code.domain() == *this);

    // Fetch message from base domain (POSIX)
    auto msg = _base::_do_message(code);
    const auto &c1 = static_cast<const file_io_error &>(code);  // NOLINT
    const value_type &v = c1.value();

    // Append my source file and line number
    if(v.file == nullptr)
      return msg;
    size_t length = strlen(v.file) + 16 + msg.size();
    auto *p = static_cast<char *>(malloc(length));  // NOLINT
    if(p == nullptr)
      return _base::string_ref("failed to get message from system");
    sprintf(p, "%s (%s:%d)",, v.file, v.lineno);

    // Return as atomically reference counted string
    return _base::atomic_refcounted_string_ref(p, length);
View this code on Github