Using std::error_code with non-integer values

c++, c++11, error-code

Solution

As mentioned in the comments, you must know the error codes, which could be received from the remote server. The `std::string` which you receive from a remote server contains 2 parts as you said,

The problem is that these are identified by strings, eg, "0A01" and also contain a message, and error code requires an integer as value.

As you haven't shared the format of the error message, I am not adding the code for spiting it, split your string into 2 parts,

- Error Code

- Error Message

Now you can convert Error Code of type `std::string` to `int` by using `std::stoi(error_code)`, So lets say

int error_code_int = std::stoi(string_to_hexadecimal(error_code));

And for `std::error_category` which serves as base class for our custom error messages, do this,

std::string message_received = "This is the message which received from remote server.";

struct OurCustomErrCategory : std::error_category
{
  const char* name() const noexcept override;
  std::string message(int ev) const override;
};

const char* OurCustomErrCategory::name() const noexcept
{
  return "Error Category Name";
}

std::string OurCustomErrCategory::message(int error_code_int) const
{
    switch (error_code_int)
    {
    case 1:
        return message_received;

    default:
        return "(unrecognized error)";
  }
}

const OurCustomErrCategory ourCustomErrCategoryObject;

std::error_code make_error_code(int e)
{
  return {e, ourCustomErrCategoryObject};
}

int main()
{
    int error_code_int = std::stoi(string_to_hexadecimal(error_code));  // error_code = 0A01
    ourCustomErrCategoryObject.message(error_code_int);
    std::error_code ec(error_code_int , ourCustomErrCategoryObject);
    assert(ec);

    std::cout << ec << std::endl;
    std::cout << ec.message() << std::endl;
}

The output for above working example is

Error Category Name : 0A01
This is the message which received from remote server.

You can use function `string_to_hexadecimal()` from this post.

I hope that now you can modify the above code according to your needs.

Edit 1:

As you said that:

This assumes the dynamic message is a global value. How do I pass it to an `std::error_category` object?

You can see that both `std::error_code::assign` and constructor `std::error_code::error_code` are taking parameters of `int` for error code number and `error_category`. So It is obvious that `std::error_code` can't take the dynamic message.

But wait, I said `std::error_code` are taking `error_category` as an argument in constructor, so is there any way, we can assign the dynamic message there ?

`std::error_category` states that:

`std::error_category` serves as the base class for specific error category types.

So it means that the `struct` we derived from `std::error_category` at the following line

struct OurCustomErrCategory : std::error_category

can have a data member and we can assign it via member function, so our `struct` will become like that,

struct OurCustomErrCategory : std::error_category
{
    std::string message_received;
    OurCustomErrCategory(std::string m) : message_received(m) {}

    const char* name() const noexcept override;
    std::string message(int ev) const override;
};

and you can assign it like that wherever you want,

const OurCustomErrCategory ourCustomErrCategoryObject("This is the message which received from remote server.");

Problem

I'm writing a library and want to return error codes whenever an error is returned by a remote system. The problem is that these are identified by strings, eg, "0A01" and also contain a message, and error code requires an integer as value. What is the best way to implement an error code, with all the functionality that `std::error_code` provides but that uses strings as the value? How do I add an external error string to the `std::error_code` or `std::error_category`?

Original source

Related problems