ned14 / status-code

Proposed SG14 status_code for the C++ standard

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When to use `error` and when to use `status_code` from SYSTEM_ERROR2_NAMESPACE

qknight opened this issue · comments

Hey,

with this example below, copied from the Readme.md we assign:

SYSTEM_ERROR2_CONSTEXPR14 auto v = another_namespace::status_code(another_namespace::AnotherCode::success1);
SYSTEM_ERROR2_NAMESPACE::error err = v;

This terminates the program according to the check in the source in status_code.hpp!

We wonder why should I use SYSTEM_ERROR2_NAMESPACE::error vs. SYSTEM_ERROR2_NAMESPACE::status_code at all? When does it make sense to use ::error and when to use ::status_code

Readme.md (the source code with small adaptions)

// qknight: added example code from status-code readme.md to play with
// https://github.com/ned14/status-code#quick-synthesis-of-a-custom-status-code-domain-for-any-arbitrary-enumeration-type

#ifdef _WIN32
#include "com_code.hpp"
#else
#include "getaddrinfo_code.hpp"
#endif

#include "iostream_support.hpp"
#include "std_error_code.hpp"
#include "system_error2.hpp"

#include <cstdio>
#include <cstring>  // for strdup, strlen
#include <iostream>
#include <memory>
#include <string>
#include <assert.h>

// This is some third party enumeration type in another namespace
namespace another_namespace
{
    // "Initialiser list" custom status code domain
    enum class AnotherCode : size_t
    {
        success1,
        goaway,
        success2,
        error2
    };
}  // namespace another_namespace


// To synthesise a custom status code domain for `AnotherCode`, inject the following
// template specialisation:
SYSTEM_ERROR2_NAMESPACE_BEGIN



template <>
struct quick_status_code_from_enum<another_namespace::AnotherCode>
        : quick_status_code_from_enum_defaults<another_namespace::AnotherCode>
{
    // Text name of the enum
    static constexpr const auto domain_name = "Another Code";

    // Unique UUID for the enum. PLEASE use https://www.random.org/cgi-bin/randbyte?nbytes=16&format=h
    static constexpr const auto domain_uuid = "{be201f65-3962-dd0e-1266-a72e63776a42}";

    // Map of each enum value to its text string, and list of semantically equivalent errc's
    static const std::initializer_list<mapping> &value_mappings()
    {
        static const std::initializer_list<mapping> v = {
                // Format is: { enum value, "string representation", { list of errc mappings ... } }
                {another_namespace::AnotherCode::success1, "Success 1", {errc::success}},        //
                {another_namespace::AnotherCode::goaway, "Go away", {errc::permission_denied}},  //
                {another_namespace::AnotherCode::success2, "Success 2", {errc::success}},        //
                {another_namespace::AnotherCode::error2, "Error 2", {}},                         //
        };
        return v;
    }

    // Completely optional definition of mixin for the status code synthesised from `Enum`.
    // It can be omitted.
    template <class Base> struct mixin : Base
    {
        using Base::Base;

        // A custom method on the synthesised status code
        constexpr int custom_method() const { return 42; }
    };
};


SYSTEM_ERROR2_NAMESPACE_END



// If you wish easy manufacture of status codes from AnotherCode:
namespace another_namespace
{
    // ADL discovered, must be in same namespace as AnotherCode
    constexpr inline
    SYSTEM_ERROR2_NAMESPACE::quick_status_code_from_enum_code<AnotherCode>
    status_code(AnotherCode c) { return c; }
}  // namespace another_namespace

void example4() {
// Make a status code of the synthesised code domain for `AnotherCode`
    SYSTEM_ERROR2_CONSTEXPR14 auto v = another_namespace::status_code(another_namespace::AnotherCode::success1);

// If you don't need custom methods, just use system_code, all erased
// status codes recognise quick_status_code_from_enum
    SYSTEM_ERROR2_NAMESPACE::system_code v2(another_namespace::AnotherCode::error2);

    // this ends the program, but why should i use SYSTEM_ERROR2_NAMESPACE::error vs. SYSTEM_ERROR2_NAMESPACE::system_code at all?
    SYSTEM_ERROR2_NAMESPACE::error err = v;

    std::cout << "executing two asserts... in example 4" << std::endl;
    assert(v.value() == another_namespace::AnotherCode::success1);
    assert(v.custom_method() == 42);
};

Additional wish

Could you add this code to the examples/ folder also?

with this example below, copied from the Readme.md we assign:

SYSTEM_ERROR2_CONSTEXPR14 auto v = another_namespace::status_code(another_namespace::AnotherCode::success1);
SYSTEM_ERROR2_NAMESPACE::error err = v;

This terminates the program according to the check in the source in status_code.hpp!

We wonder why should I use SYSTEM_ERROR2_NAMESPACE::error vs. SYSTEM_ERROR2_NAMESPACE::status_code at all? When does it make sense to use ::error and when to use ::status_code

The relationship here is as follows:

  • system_code is a status_code erased into an intptr_t.
  • error is an errored_status_code erased into an intptr_t.
  • errored_status_code is a status_code for whom it is guaranteed that .success() is false, which was originally going to be guaranteed using C++ contracts before those got axed. The next closest equivalent to Contracts is terminating the process.

So the idea is that an operation can return a status code which may be successful (e.g. with warning or additional info), or may be a failure with cause. If you wish to promise in the C++ type system that a status code will always be a failure, you use errored_* or error. The compiler may be able to make extra optimisations in this situation (no current compiler can).

Hopefully that makes sense.

Re: adding the quick status code from enum example, no problem I'll do that there now.