Skip to content

Commit

Permalink
Merge branch 'ned14:develop' into zig-pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
kassane authored Aug 4, 2024
2 parents 7560a9d + a4f6b1b commit 5c7a38a
Show file tree
Hide file tree
Showing 50 changed files with 3,013 additions and 993 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unittests_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: CMake tests Linux
shell: bash
run: |
sudo apt-get remove -y libstdc++-10-dev g++-10 gcc-10 libstdc++-11-dev g++-11 gcc-11
sudo apt-get remove -y libstdc++-10-dev g++-10 gcc-10 libstdc++-11-dev g++-11 gcc-11 || true
sudo apt-get autoremove
if [ "${{ matrix.compiler }}" = "libc++" ]; then
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -;
Expand Down
26 changes: 26 additions & 0 deletions boostify/build.jam
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright René Ferdinand Rivera Morell 2023-2024
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)

require-b2 5.2 ;

constant boost_dependencies :
/boost/assert//boost_assert
/boost/config//boost_config
/boost/exception//boost_exception
/boost/system//boost_system
/boost/throw_exception//boost_throw_exception ;

project /boost/outcome
: common-requirements
<include>include
;

explicit
[ alias boost_outcome : : : : <library>$(boost_dependencies) ]
[ alias all : boost_outcome test ]
;

call-if : boost-library outcome
;
13 changes: 8 additions & 5 deletions boostify/test/Jamfile.v2
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Boost.Outcome Library test Jamfile
#
# Copyright (C) 2017-2019 Niall Douglas
# Copyright (C) 2017-2024 Niall Douglas
#
# Use, modification, and distribution is subject to the Boost Software
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Expand All @@ -9,17 +9,20 @@
# See http://www.boost.org/libs/outcome for documentation.

import testing ;
import ../../config/checks/config : requires ;
import ../../predef/tools/check/predef : check require : predef-check predef-require ;
import-search /boost/config/checks ;
import config : requires ;
import-search /boost/predef/tools/check ;
import predef : check require : predef-check predef-require ;

project
: requirements
[ requires cxx14_variable_templates cxx14_constexpr ]
[ predef-require "!BOOST_COMP_GNUC" or "BOOST_COMP_GNUC >= 6.0" ]
[ predef-require "!BOOST_COMP_CLANG" or "BOOST_COMP_CLANG >= 4.0" ]
<define>BOOST_TEST_MODULE=Outcome
<library>../../test/build//boost_unit_test_framework
;
<library>/boost/test//boost_unit_test_framework
<library>/boost/outcome//boost_outcome
;

{
test-suite outcome :
Expand Down
2 changes: 2 additions & 0 deletions cmake/headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ set(outcome_HEADERS
"include/outcome/detail/revision.hpp"
"include/outcome/detail/trait_std_error_code.hpp"
"include/outcome/detail/trait_std_exception.hpp"
"include/outcome/detail/try.h"
"include/outcome/detail/value_storage.hpp"
"include/outcome/detail/version.hpp"
"include/outcome/experimental/coroutine_support.hpp"
Expand Down Expand Up @@ -55,6 +56,7 @@ set(outcome_HEADERS
"include/outcome/iostream_support.hpp"
"include/outcome/outcome.hpp"
"include/outcome/outcome.natvis"
"include/outcome/outcome_gdb.h"
"include/outcome/policy/all_narrow.hpp"
"include/outcome/policy/base.hpp"
"include/outcome/policy/fail_to_compile_observers.hpp"
Expand Down
1 change: 1 addition & 0 deletions cmake/tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ set(outcome_TESTS
"test/tests/core-result.cpp"
"test/tests/coroutine-support.cpp"
"test/tests/default-construction.cpp"
"test/tests/experimental-c-result.cpp"
"test/tests/experimental-core-outcome-status.cpp"
"test/tests/experimental-core-result-status.cpp"
"test/tests/experimental-p0709a.cpp"
Expand Down
2 changes: 1 addition & 1 deletion doc/html
Submodule html updated 493 files
20 changes: 19 additions & 1 deletion doc/src/content/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Outcome is a set of tools for reporting and handling function failures in contex

- where interoperation with C code, without having to resort to C++ exception wrapper shims, is important.

- where your mostly C code base needs exception-like error handling, and the subset of Outcome's functionality available in C is sufficient for your needs.

Outcome addresses failure handling through returning a special type from functions, which is able to store either a successfully computed value (or `void`), or the information about failure. Outcome also comes with a set of idioms for dealing with such types.

Particular care has been taken to ensure that Outcome has the lowest possible impact on build times,
Expand All @@ -44,7 +46,7 @@ Fully deterministic all-`noexcept` C++ Coroutine support in Outcome is particula
supply Outcome-optimising {{< api "eager<T, Executor = void>/atomic_eager<T, Executor = void>" >}}, {{< api "lazy<T, Executor = void>/atomic_lazy<T, Executor = void>" >}}
and {{<api "generator<T, Executor = void>" >}} awaitables which work for any user type.

## Sample usage
## Sample usage (C++)

The main workhorse in the Outcome library is `result<T>`: it represents either a successfully computed value of type `T`, or a `std::error_code`/`boost::system::error_code`[^2] representing the reason for failure. You use it in the function's return type:

Expand All @@ -61,6 +63,22 @@ Or, if this function is called in another function that also returns `result<T>`
`OUTCOME_TRY` is a control statement. If the returned `result<T>` object contains an error information, the enclosing function is immediately returned with `result<U>` containing the same failure information; otherwise an automatic object of type `T`
is available in scope.

## Sample usage \(C)

Equivalent to the C++ API: `CXX_DECLARE_RESULT_SYSTEM(ident, T)` declares the C type, thereafter `CXX_RESULT_SYSTEM(ident)` refers to it. You use it in the function's return type:

{{% snippet "intro_c_example.cpp" "signature" %}}

It is possible to inspect the state manually:

{{% snippet "intro_c_example.cpp" "inspect" %}}

Or, if this function is called in another function that also returns `CXX_RESULT_SYSTEM(ident)`, you can use a dedicated control statement:

{{% snippet "intro_c_example.cpp" "implementation" %}}

The C Result is guaranteed to be layout identical to its C++ equivalent. Convenience conversion functions are available, but you can reinterpret cast too.

{{% notice note %}}
This library joined [the Boost C++ libraries](https://www.boost.org/doc/libs/develop/libs/outcome/doc/html/index.html) in the 1.70 release (Spring 2019). [It can be grafted into much older Boost releases if desired](https://github.com/boostorg/outcome).
{{% /notice %}}
Expand Down
37 changes: 34 additions & 3 deletions doc/src/content/changelog/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,40 @@ weight = 80
+++

---
## v2.2.9 ? (Boost 1.85) [[release]](https://github.com/ned14/outcome/releases/tag/v2.2.9)
## v2.2.11 ? (Boost 1.87) [[release]](https://github.com/ned14/outcome/releases/tag/v2.2.11)

### Enhancements:

- Outcome.Experimental has had C representation support since the beginning, however it had
been mainly intended that C++ would originate Results, they would pass through C, and back
into C++. It hadn't really been expected that C would want to do much with Results other than
inspect them for happy or sad path.

It turns out there is more demand than expected for a more functional Result from within C,
so this release adds the power to create Results in success and two types of failure, semantic
comparison of Results, and printing of Result messages. You can also wrap a C enum into a
quick status code from enum, allowing easy custom C error coding from 100% within C.

[The documentation for the C support]({{% relref "../experimental/c-api" %}}) has been updated
to reflect the new facilities.

### Bug fixes:

---
## v2.2.10 14th August 2024 (Boost 1.86) [[release]](https://github.com/ned14/outcome/releases/tag/v2.2.10)

### Enhancements:

- Something I've been meaning to do for far too long now is make the GDB pretty printers
auto-loading so you don't have to set up `.gdbinit`. This is now done. I also improved
the pretty printers to also pretty print the C result type which can be very useful if
working with that type, as it will print the error message in GDB.

Experimental Outcome's `status_code` has also gained its own auto-loading GDB pretty printer
with display of `strerror()` if the code domain is POSIX or generic.

---
## v2.2.9 15th April 2024 (Boost 1.85) [[release]](https://github.com/ned14/outcome/releases/tag/v2.2.9)

### Enhancements:

Expand All @@ -24,8 +57,6 @@ realised at the time that in Boost.Outcome this resulted in
This has now been remedied to remove the double `status-code`, which will obviously break
any Boost.Outcome code which relies on the double `status-code`. Standalone Outcome is unaffected.

### Bug fixes:

---
## v2.2.8 13th December 2023 (Boost 1.84) [[release]](https://github.com/ned14/outcome/releases/tag/v2.2.8)

Expand Down
3 changes: 3 additions & 0 deletions doc/src/content/experimental/advantages.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ and the dual target source code, being written to tighter discipline,
is faster and more deterministic in the default target than it was before
the (non-trivial) port to `<outcome/experimental>`.

5. If you want 'official' C support, experimental Outcome is able to
provide that in a way not possible for default Outcome which cannot make
sufficiently strong C compatibility assumptions about `std::error_code`.

If you are building a codebase on top of Outcome expecting long term
maintenance, the author's personal recommendation is that you design, write, test and
Expand Down
51 changes: 51 additions & 0 deletions doc/src/content/experimental/c-api/from-c/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
+++
title = "C Results"
description = "Outcome's C Result support"
weight = 30
+++

The C macro API header `<outcome/experimental/result.h>` has some macros for working with any kind of Result:

<dl>
<dt><code>CXX_DECLARE_RESULT(ident, T, E)</code>
<dd>Declares to C a <code>basic_result<T, E></code> type uniquely
identified by <code>ident</code>. <code>T</code> is available at the
member variable <code>.value</code>, and <code>E</code> is available
at the member variable <code>.error</code>. If you call this from within
C++, make SURE it is not within a <code>extern "C"</code> block!

<dt><code>CXX_RESULT(ident)</code>
<dd>A reference to a previously declared <code>result</code> type with
unique <code>ident</code>.

<dt><code>CXX_RESULT_HAS_VALUE(r)</code>
<dd>Evaluates to 1 (true) if the input <code>result</code> has a value.

<dt><code>CXX_RESULT_HAS_ERROR(r)</code>
<dd>Evaluates to 1 (true) if the input <code>result</code> has an error.

<dt><code>CXX_RESULT_ERROR_IS_ERRNO(r)</code>
<dd>Evaluates to 1 (true) if the input <code>result</code>'s error value
is a code in the POSIX <code>errno</code> domain.
</dl>

The above let you work, somewhat awkwardly, with any C-compatible
`basic_result<T, E>`. `basic_result<T, E>` is trivially copyable and
standard layout if its `T` and `E` are both so, and it has the C layout:

```c++
struct cxx_result_##ident
{
union
{
T value;
E error;
};
unsigned flags;
};
```

Note that this layout is different to that of [`CXX_DECLARE_STATUS_CODE`]({{% relref "../from-c" %}})
as the C++ `result` has a different layout if `E` is a status code.


11 changes: 11 additions & 0 deletions doc/src/content/experimental/c-api/from-c/declare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
+++
title = "Declare a Result"
description = "Declaring a C Result"
weight = 20
+++

{{% snippet "c_api2.cpp" "preamble" %}}

The key to making C programming easy is to alias the long complex things
into short easy thing. Obviously `SUCCESS(expr)` and `FAILURE(expr)` is too
generic, but for the purposes of this documentation it makes thing easier.
101 changes: 101 additions & 0 deletions doc/src/content/experimental/c-api/from-c/system_code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
+++
title = "C system error results"
description = "Status code's `std::error` in C"
weight = 10
+++

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>`]({{% relref "../../status_result" %}})
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:

<dl>
<dt><code>CXX_DECLARE_RESULT_SYSTEM(ident, T)</code>
<dd>Declares to C a <code>status_result<T></code> type uniquely
identified by <code>ident</code>. <code>T</code> is available at the
member variable <code>.value</code>, and <code>struct cxx_status_code_system</code>
is available at the member variable <code>.error</code>. 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 <code>extern "C"</code> block!

<dt><code>CXX_RESULT_SYSTEM(ident)</code>
<dd>A reference to a previously declared <code>status_result</code> type with
unique <code>ident</code>.

<dt><code>CXX_MAKE_RESULT_SYSTEM_SUCCESS(ident, expr)</code> (needs C++ counterpart linked into final binary)
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code>
with a successful value of type <code>T</code>.
<dt><code>CXX_MAKE_RESULT_SYSTEM_FAILURE_POSIX(ident, expr)</code> (needs C++ counterpart linked into final binary)
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code>
with a failure of type <code>posix_code</code> representing a POSIX <code>errno</code>.
<dt><code>CXX_MAKE_RESULT_SYSTEM_FAILURE_SYSTEM(ident, expr)</code> (needs C++ counterpart linked into final binary)
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code>
with a failure of type <code>posix_code</code> representing a POSIX <code>errno</code>
if on POSIX; if on Windows then a failure of type <code>win32_code</code>
representing a Win32 error code from a Windows API.

<br><br>
<dt><code>CXX_RESULT_HAS_VALUE(r)</code>
<dd>Evaluates to 1 (true) if the input <code>result</code> has a value.

<dt><code>CXX_RESULT_HAS_ERROR(r)</code>
<dd>Evaluates to 1 (true) if the input <code>result</code> has an error.

<dt><code>CXX_RESULT_ERROR_IS_ERRNO(r)</code>
<dd>Evaluates to 1 (true) if the input <code>result</code>'s error value
is a code in the POSIX <code>errno</code> domain.
<br><br>
<dt><code>CXX_RESULT_SYSTEM_TRY(expr)</code>
<dd>If the <code>status_result</code> returned by <code>expr</code> is
errored, exit the current function returning the result. This obviously
requires that the return type of the current function matches that of <code>
expr</code>.

<dt><code>CXX_RESULT_SYSTEM_TRY(cleanup, expr)</code>
<dd>Same as the above, but execute <code>cleanup</code> just before exiting the function
if returning failure.

<dt><code>CXX_RESULT_SYSTEM_TRY(var, cleanup, expr)</code>
<dd>Same as the above, but set <code>var</code> equal to the result's <code>.value</code> on success.

<dt><code>CXX_RESULT_SYSTEM_TRY(var, ident, cleanup, expr)</code>
<dd>Same as the above, but use <code>ident</code> as the return type instead. This allows
the return type of the calling function to differ from that of <code>expr</code>.
<br><br>
<dt><code>CXX_DECLARE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, uuid, {enum mapping-sequence, ...})</code>
<dd>This declares to C an extern function which creates a <code>status_result</code>
from a C enum. If in C++, it implements a <code>quick_status_code_from_enum</code> for
the C enum and the associated extern function, and you will need to supply <code>uuid</code>
and the appropriate enum value mapping sequence <a href="{{% relref "../../worked-example" %}}">
as per the <code>quick_status_code_from_enum</code> documentation</a>.
<dt><code>CXX_MAKE_RESULT_SYSTEM_FROM_ENUM(ident, enum_name, expr)</code> (needs C++ counterpart linked into final binary)
<dd>This invokes the aforementioned extern function which creates a <code>status_result</code>
from a C enum.
</dl>

The operations available to C++ are:

<dl>
<dt><code>CXX_TO_RESULT_SYSTEM_CODE(ident, status_code&lt;T&gt;)</code>
<dd>Returns a previously declared C Result from its matching C++ <code>status_code</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.

<dt><code>to_result(any C Result)</code>
<dd>This is an overloaded C++ free function which returns the C++ status_code&lt;T&gt;
matching its input C Result.
</dl>

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.
18 changes: 18 additions & 0 deletions doc/src/content/experimental/c-api/from-c/try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
+++
title = "TRY a C Result"
description = "Operation TRY on a C Result"
weight = 40
+++

Thanks to much of the magic of {{< api "OUTCOME_TRY(var, expr)" >}} being implemented
using C preprocessor metaprogramming, we can offer a very similar experience for the
C try operation and without needing anything compiled in C++ as support functions:

{{% snippet "c_api2.cpp" "try" %}}

The principle difference is that you can specify a cleanup routine to perform if
failure is encountered. This is especially useful in C, which has no stack unwinding.

Also due to lack of type sugaring and user defined implicit conversions, if your
callers result type isn't your callee's, you may need to specify what your caller's
result type is so the error state can be correctly propagated.
14 changes: 14 additions & 0 deletions doc/src/content/experimental/c-api/from-c/use.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
+++
title = "Using a Result"
description = "Using a C Result"
weight = 30
+++

This models [the earlier C++ example of use]({{% relref "/experimental/worked-example/implicit-construction" %}}),
and its C equivalent isn't much more verbose thanks to our helper typedefs and macros:

{{% snippet "c_api2.cpp" "using" %}}

For this to link, the `CXX_DECLARE_RESULT_SYSTEM_FROM_ENUM` macro needs to be
compiled at least once within C++ within the final binary to emit the extern
functions needed by C.
Loading

0 comments on commit 5c7a38a

Please sign in to comment.