C system error results

In v2.2.11, C Result support went from second tier to first tier status, and now you can create, query and manipulate a subset of Result types entirely from within C by including <outcome/experimental/result.h>.

The subset supported are those result<T, E> which are a status_result<T> i.e. the E is hardcoded to experimental::error which is the type erased runtime polymorphic holder for any errored status_code whose payload is not bigger than an intptr_t. This is the most useful subset of Outcome Experimental’s possible Result types, allowing arbitrary custom error coding schemes from any unknown source to work seamlessly with all others, including errors from the system or third party libraries.

The operations available to C are:

CXX_DECLARE_RESULT_SYSTEM(ident, T)
Declares to C a status_result type uniquely identified by ident. T is available at the member variable .value, and struct cxx_status_code_system is available at the member variable .error. If in C++, implements C extern functions for making successful and failure results of this type. If you call this from within C++, make SURE it is not within a extern "C" block!
CXX_RESULT_SYSTEM(ident)
A reference to a previously declared status_result type with unique ident.
CXX_MAKE_RESULT_SYSTEM_SUCCESS(ident, expr) (needs C++ counterpart linked into final binary)
This invokes the aforementioned extern function which creates a status_result with a successful value of type T.
CXX_MAKE_RESULT_SYSTEM_FAILURE_POSIX(ident, expr) (needs C++ counterpart linked into final binary)
This invokes the aforementioned extern function which creates a status_result with a failure of type posix_code representing a POSIX errno.
CXX_MAKE_RESULT_SYSTEM_FAILURE_SYSTEM(ident, expr) (needs C++ counterpart linked into final binary)
This invokes the aforementioned extern function which creates a status_result with a failure of type posix_code representing a POSIX errno if on POSIX; if on Windows then a failure of type win32_code representing a Win32 error code from a Windows API.

CXX_RESULT_HAS_VALUE(r)
Evaluates to 1 (true) if the input result has a value.
CXX_RESULT_HAS_ERROR(r)
Evaluates to 1 (true) if the input result has an error.
CXX_RESULT_ERROR_IS_ERRNO(r)
Evaluates to 1 (true) if the input result's error value is a code in the POSIX errno domain.

CXX_RESULT_SYSTEM_TRY(expr)
If the status_result returned by expr is errored, exit the current function returning the result. This obviously requires that the return type of the current function matches that of expr.
CXX_RESULT_SYSTEM_TRY(cleanup, expr)
Same as the above, but execute cleanup just before exiting the function if returning failure.
CXX_RESULT_SYSTEM_TRY(var, cleanup, expr)
Same as the above, but set var equal to the result's .value on success.
CXX_RESULT_SYSTEM_TRY(var, ident, cleanup, expr)
Same as the above, but use ident as the return type instead. This allows the return type of the calling function to differ from that of expr.

CXX_DECLARE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, uuid, {enum mapping-sequence, ...})
This declares to C an extern function which creates a status_result from a C enum. If in C++, it implements a quick_status_code_from_enum for the C enum and the associated extern function, and you will need to supply uuid and the appropriate enum value mapping sequence as per the quick_status_code_from_enum documentation.
CXX_MAKE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, expr) (needs C++ counterpart linked into final binary)
This invokes the aforementioned extern function which creates a status_result from a C enum.

The operations available to C++ are:

CXX_TO_RESULT_SYSTEM_CODE(ident, status_code<T>)
Returns a previously declared C Result from its matching C++ status_code. NOTE that the destructor of the C++ status code is NOT called. If this is important to your status code, it is 100% on you to ensure that your C Result reenters a C++ Result at the end of its lifetime.
to_result(any C Result)
This is an overloaded C++ free function which returns the C++ status_code<T> matching its input C Result.

Using the above you can write C code using Outcome.Experimental’s Result type quite effectively. Let’s look at an example of use next.