Skip to content

Commit 19d8353

Browse files
committed
Add WG14 reference C reimplementation of Outcome.
1 parent 71c42c0 commit 19d8353

File tree

7 files changed

+157
-5
lines changed

7 files changed

+157
-5
lines changed

.boostify

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include_files = [
1010
]
1111
exclude_files = [
1212
r'.*quickcpplib.*',
13+
r'.*wg14.result.*',
1314
r'^include/outcome/experimental/status-code/(?!include)',
1415
r'^include/outcome.ixx',
1516
r'.*\.natvis$',

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@
1818
branch = master
1919
fetchRecurseSubmodules = true
2020
ignore = untracked
21+
[submodule "include/outcome/experimental/wg14_result"]
22+
path = include/outcome/experimental/wg14_result
23+
url = https://github.com/ned14/wg14_result.git

CMakeLists.txt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (
190190
"outcome_hl--core-result"
191191
"outcome_hl--fileopen"
192192
"outcome_hl--hooks"
193+
"outcome_hl--experimental-wg14-result"
193194
"outcome_hl--outcome-int-int-1"
194195
"outcome_hl--result-int-int-1"
195196
"outcome_hl--result-int-int-2"
@@ -205,6 +206,9 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (
205206
if(MSVC AND NOT CLANG)
206207
target_compile_options(${target} PRIVATE /permissive-)
207208
endif()
209+
if(${target} MATCHES "experimental-wg14-result")
210+
target_compile_features(${target} PUBLIC cxx_std_20)
211+
endif()
208212
endforeach()
209213

210214
# Duplicate all tests into C++ exceptions disabled forms
@@ -219,11 +223,14 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (
219223
add_executable(${target_name} "${testsource}")
220224
if(NOT first_test_target_noexcept)
221225
set(first_test_target_noexcept ${target_name})
222-
elseif(${target_name} MATCHES "coroutine-support|fileopen|hooks|core-result")
226+
elseif(${target_name} MATCHES "coroutine-support|fileopen|hooks|core-result|experimental-wg14-result")
223227
set_target_properties(${target_name} PROPERTIES DISABLE_PRECOMPILE_HEADERS On)
224228
elseif(COMMAND target_precompile_headers)
225229
target_precompile_headers(${target_name} REUSE_FROM ${first_test_target_noexcept})
226230
endif()
231+
if(${target_name} MATCHES "experimental-wg14-result")
232+
target_compile_features(${target_name} PUBLIC cxx_std_20)
233+
endif()
227234
add_dependencies(_hl ${target_name})
228235
list(APPEND noexcept_tests ${target_name})
229236
if(MSVC AND NOT CLANG)
@@ -250,11 +257,14 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test" AND NOT outcome_IS_DEPENDENCY AND (
250257
add_executable(${target_name} "${testsource}")
251258
if(NOT first_test_target_permissive)
252259
set(first_test_target_permissive ${target_name})
253-
elseif(${target_name} MATCHES "coroutine-support|fileopen|core-result")
260+
elseif(${target_name} MATCHES "coroutine-support|fileopen|core-result|experimental-wg14-result")
254261
set_target_properties(${target_name} PROPERTIES DISABLE_PRECOMPILE_HEADERS On)
255262
elseif(COMMAND target_precompile_headers)
256263
target_precompile_headers(${target_name} REUSE_FROM ${first_test_target_permissive})
257264
endif()
265+
if(${target_name} MATCHES "experimental-wg14-result")
266+
target_compile_features(${target_name} PUBLIC cxx_std_20)
267+
endif()
258268
add_dependencies(_hl ${target_name})
259269
target_link_libraries(${target_name} PRIVATE outcome::hl)
260270
target_compile_options(${target_name} PRIVATE /permissive)

cmake/tests.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ set(outcome_TESTS
1313
"test/tests/experimental-core-outcome-status.cpp"
1414
"test/tests/experimental-core-result-status.cpp"
1515
"test/tests/experimental-p0709a.cpp"
16+
"test/tests/experimental-wg14-result.cpp"
1617
"test/tests/fileopen.cpp"
1718
"test/tests/hooks.cpp"
1819
"test/tests/issue0007.cpp"

include/outcome/detail/revision.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ Distributed under the Boost Software License, Version 1.0.
2222
*/
2323

2424
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
25-
#define OUTCOME_PREVIOUS_COMMIT_REF 744da6b7536f2850df972ab01504e3c4d9530149
26-
#define OUTCOME_PREVIOUS_COMMIT_DATE "2025-05-21 12:10:22 +00:00"
27-
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 744da6b7
25+
#define OUTCOME_PREVIOUS_COMMIT_REF eca310058309b1d731a7d167ff68b970bbf47fa5
26+
#define OUTCOME_PREVIOUS_COMMIT_DATE "2025-10-29 18:19:00 +00:00"
27+
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE eca31005
Submodule wg14_result added at 6ea20f3
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/* Unit testing for outcomes
2+
(C) 2013-2025 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
3+
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License in the accompanying file
8+
Licence.txt or at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
19+
Distributed under the Boost Software License, Version 1.0.
20+
(See accompanying file Licence.txt or copy at
21+
http://www.boost.org/LICENSE_1_0.txt)
22+
*/
23+
24+
#if !defined(SYSTEM_ERROR2_NOT_POSIX) && __has_include("../../include/outcome/experimental/wg14_result/include/wg14_result/status_code.h")
25+
26+
#ifdef __GNUC__
27+
#pragma GCC diagnostic ignored "-Wunused-function"
28+
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
29+
#endif
30+
#ifdef _MSC_VER
31+
#pragma warning(disable : 4505) // unreferenced function has been removed
32+
#endif
33+
34+
#define WG14_RESULT_ENABLE_HEADER_ONLY 1
35+
36+
#include "../../include/outcome/experimental/wg14_result/include/wg14_result/status_code.h"
37+
#include "../../include/outcome/experimental/wg14_result/include/wg14_result/status_code_generic.h"
38+
39+
#include "../../include/outcome/experimental/status-code/include/status-code/config.hpp"
40+
#include "../../include/outcome/experimental/status-code/include/status-code/status_code_domain.hpp"
41+
#include "../../include/outcome/experimental/status_result.hpp"
42+
43+
#include "quickcpplib/boost/test/unit_test.hpp"
44+
45+
46+
BOOST_OUTCOME_AUTO_TEST_CASE(works / status_code / wg14_status_code, "Tests that the WG14 C status_code works as intended")
47+
{
48+
// The C ones need to be ABI compatible with the C++ ones
49+
static_assert(sizeof(SYSTEM_ERROR2_NAMESPACE::generic_code) == sizeof(WG14_RESULT_PREFIX(status_code_generic)),
50+
"WG14 C status code is not the same size as the C++ status code!");
51+
static_assert(alignof(SYSTEM_ERROR2_NAMESPACE::generic_code) == alignof(WG14_RESULT_PREFIX(status_code_generic)),
52+
"WG14 C status code is not the same alignment as the C++ status code!");
53+
static_assert(sizeof(SYSTEM_ERROR2_NAMESPACE::status_code_domain) == sizeof(WG14_RESULT_PREFIX(status_code_domain)),
54+
"WG14 C status code domain is not the same size as the C++ status code domain!");
55+
static_assert(alignof(SYSTEM_ERROR2_NAMESPACE::status_code_domain) == alignof(WG14_RESULT_PREFIX(status_code_domain)),
56+
"WG14 C status code domain is not the same alignment as the C++ status code domain!");
57+
static_assert(sizeof(SYSTEM_ERROR2_NAMESPACE::status_code_domain::string_ref) == sizeof(WG14_RESULT_PREFIX(status_code_domain_string_ref)),
58+
"WG14 C status code domain string ref is not the same size as the C++ status code domain string ref!");
59+
static_assert(alignof(SYSTEM_ERROR2_NAMESPACE::status_code_domain::string_ref) == alignof(WG14_RESULT_PREFIX(status_code_domain_string_ref)),
60+
"WG14 C status code domain string ref is not the same alignment as the C++ status code domain string ref!");
61+
62+
// Construct with C edition, use with C++ edition
63+
{
64+
WG14_RESULT_CONSTEXPR_OR_CONST WG14_RESULT_PREFIX(status_code_generic)
65+
empty1 = {{WG14_RESULT_NULLPTR}, WG14_RESULT_PREFIX(status_code_errc_success)},
66+
success1 = WG14_RESULT_PREFIX(status_code_generic_make)(WG14_RESULT_PREFIX(status_code_errc_success)),
67+
failure1 = WG14_RESULT_PREFIX(status_code_generic_make)(WG14_RESULT_PREFIX(status_code_errc_permission_denied));
68+
BOOST_CHECK(status_code_is_empty(empty1));
69+
BOOST_CHECK(!status_code_is_empty(success1));
70+
BOOST_CHECK(!status_code_is_empty(failure1));
71+
BOOST_CHECK(status_code_is_success(success1));
72+
BOOST_CHECK(status_code_is_failure(failure1));
73+
printf("generic_code empty has value %d (%s) is success %d is failure %d\n", empty1.value, status_code_message(empty1).c_str,
74+
status_code_is_success(empty1), status_code_is_failure(empty1));
75+
printf("generic_code success has value %d (%s) is success %d is failure %d\n", success1.value, status_code_message(success1).c_str,
76+
status_code_is_success(success1), status_code_is_failure(success1));
77+
printf("generic_code failure has value %d (%s) is success %d is failure %d\n", failure1.value, status_code_message(failure1).c_str,
78+
status_code_is_success(failure1), status_code_is_failure(failure1));
79+
80+
#if !QUICKCPPLIB_IN_UNDEFINED_SANITIZER
81+
// For obvious reasons, ubsan really doesn't like C manufactured vptrs
82+
const SYSTEM_ERROR2_NAMESPACE::generic_code *empty1a = (const SYSTEM_ERROR2_NAMESPACE::generic_code *) &empty1,
83+
*success1a = (const SYSTEM_ERROR2_NAMESPACE::generic_code *) &success1,
84+
*failure1a = (const SYSTEM_ERROR2_NAMESPACE::generic_code *) &failure1;
85+
BOOST_CHECK(empty1a->empty());
86+
BOOST_CHECK(!success1a->empty());
87+
BOOST_CHECK(!failure1a->empty());
88+
BOOST_CHECK(success1a->success());
89+
BOOST_CHECK(failure1a->failure());
90+
printf("generic_code empty has value %d (%s) is success %d is failure %d\n", (int) empty1a->value(), empty1a->message().c_str(), empty1a->success(),
91+
empty1a->failure());
92+
printf("generic_code success has value %d (%s) is success %d is failure %d\n", (int) success1a->value(), success1a->message().c_str(), success1a->success(),
93+
success1a->failure());
94+
printf("generic_code failure has value %d (%s) is success %d is failure %d\n", (int) failure1a->value(), failure1a->message().c_str(), failure1a->success(),
95+
failure1a->failure());
96+
#endif
97+
}
98+
99+
// Construct with C++ edition, use with C edition
100+
{
101+
constexpr SYSTEM_ERROR2_NAMESPACE::generic_code empty1, success1(SYSTEM_ERROR2_NAMESPACE::errc::success),
102+
failure1(SYSTEM_ERROR2_NAMESPACE::errc::permission_denied);
103+
BOOST_CHECK(empty1.empty());
104+
BOOST_CHECK(!success1.empty());
105+
BOOST_CHECK(!failure1.empty());
106+
BOOST_CHECK(success1.success());
107+
BOOST_CHECK(failure1.failure());
108+
printf("generic_code empty has value %d (%s) is success %d is failure %d\n", static_cast<int>(empty1.value()), empty1.message().c_str(),
109+
static_cast<int>(empty1.success()), static_cast<int>(empty1.failure()));
110+
printf("generic_code success has value %d (%s) is success %d is failure %d\n", static_cast<int>(success1.value()), success1.message().c_str(),
111+
static_cast<int>(success1.success()), static_cast<int>(success1.failure()));
112+
printf("generic_code failure has value %d (%s) is success %d is failure %d\n", static_cast<int>(failure1.value()), failure1.message().c_str(),
113+
static_cast<int>(failure1.success()), static_cast<int>(failure1.failure()));
114+
115+
const WG14_RESULT_PREFIX(status_code_generic) &empty1a = *(const WG14_RESULT_PREFIX(status_code_generic) *) &empty1,
116+
&success1a = *(const WG14_RESULT_PREFIX(status_code_generic) *) &success1,
117+
&failure1a = *(const WG14_RESULT_PREFIX(status_code_generic) *) &failure1;
118+
BOOST_CHECK(status_code_is_empty(empty1a));
119+
BOOST_CHECK(!status_code_is_empty(success1a));
120+
BOOST_CHECK(!status_code_is_empty(failure1a));
121+
BOOST_CHECK(status_code_is_success(success1a));
122+
BOOST_CHECK(status_code_is_failure(failure1a));
123+
printf("generic_code empty has value %d (%s) is success %d is failure %d\n", empty1a.value, status_code_message(empty1a).c_str,
124+
status_code_is_success(empty1a), status_code_is_failure(empty1a));
125+
printf("generic_code success has value %d (%s) is success %d is failure %d\n", success1a.value, status_code_message(success1a).c_str,
126+
status_code_is_success(success1a), status_code_is_failure(success1a));
127+
printf("generic_code failure has value %d (%s) is success %d is failure %d\n", failure1a.value, status_code_message(failure1a).c_str,
128+
status_code_is_success(failure1a), status_code_is_failure(failure1a));
129+
}
130+
}
131+
#else
132+
int main(void)
133+
{
134+
return 0;
135+
}
136+
#endif

0 commit comments

Comments
 (0)