Skip to content

Commit 9a3f34a

Browse files
authored
Add conformance support for std::out_ptr (#408)
* Add conformance support for std::out_ptr * Run pre-commit * Ensure tests execute all paths * Run pre-commit
1 parent 52a4667 commit 9a3f34a

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

conanfile.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ def useRanges(self):
133133
(compiler == "clang" and version >= Version("16")) or (compiler == "apple-clang" and version >= Version("15"))
134134
return not std_support
135135

136+
@property
137+
def useOutPtr(self):
138+
""" Does the current compiler version lack support for std::out_ptr via the STL. """
139+
compiler = self.settings.compiler
140+
version = Version(self.settings.compiler.version)
141+
std_support = (compiler == "msvc" and version >= 193) or (compiler == "gcc" and version >= Version("14")) or \
142+
(compiler == "clang" and version >= Version("19"))
143+
return not std_support
144+
136145
def config_options(self):
137146
if not self.checkMoldIsSupported():
138147
self.options.rm_safe("link_with_mold")
@@ -183,6 +192,9 @@ def requirements(self):
183192
if self.useRanges:
184193
self.requires("range-v3/0.12.0", transitive_headers=True)
185194

195+
if self.useOutPtr:
196+
self.requires("out_ptr/cci.20211119", transitive_headers=True)
197+
186198
def system_requirements(self):
187199
if self.options.get_safe("with_rs_opengl", False):
188200
apt = Apt(self)

libraries/core/lib/morpheus/core/conformance/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ target_sources(MorpheusCore
77
date.hpp
88
format.hpp
99
expected.hpp
10+
outptr.hpp
1011
print.hpp
1112
ranges.hpp
1213
scan.hpp
@@ -38,6 +39,13 @@ morpheus_conformance_check(
3839
CLANG_VERSION "19"
3940
)
4041

42+
morpheus_conformance_check(
43+
RESULT OUTPTR_SUPPORTED
44+
MSVC_VERSION "19.37"
45+
GNU_VERSION "14"
46+
CLANG_VERSION "19"
47+
)
48+
4149
morpheus_conformance_check(
4250
RESULT RANGES_SUPPORTED
4351
MSVC_VERSION "19.29"
@@ -58,6 +66,10 @@ if (NOT ${FORMAT_SUPPORTED})
5866
find_package(fmt REQUIRED)
5967
endif (NOT ${FORMAT_SUPPORTED})
6068

69+
if (NOT ${OUTPTR_SUPPORTED})
70+
find_package(out_ptr REQUIRED)
71+
endif (NOT ${OUTPTR_SUPPORTED})
72+
6173
if (NOT ${RANGES_SUPPORTED})
6274
find_package(range-v3 REQUIRED)
6375
endif (NOT ${RANGES_SUPPORTED})
@@ -80,6 +92,7 @@ target_link_libraries(MorpheusCore
8092
$<$<NOT:$<BOOL:${DATE_SUPPORTED}>>:date::date>
8193
$<$<NOT:$<BOOL:${DATE_SUPPORTED}>>:date::date-tz>
8294
$<$<NOT:$<BOOL:${FORMAT_SUPPORTED}>>:fmt::fmt>
95+
$<$<NOT:$<BOOL:${OUTPTR_SUPPORTED}>>:out_ptr::out_ptr>
8396
$<$<NOT:$<BOOL:${RANGES_SUPPORTED}>>:range-v3::range-v3>
8497
scn::scn
8598
$<$<NOT:$<BOOL:${EXPECTED_SUPPORTED}>>:tl::expected>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include <morpheus/core/conformance/version.hpp>
4+
5+
// clang-format off
6+
#if (__cpp_lib_out_ptr >= 202106L)
7+
#include <memory> // IWYU pragma: export
8+
namespace morpheus::conf { namespace ptr = ::std; }
9+
#else
10+
#include <ztd/out_ptr.hpp> // IWYU pragma: export
11+
namespace morpheus::conf { namespace ptr = ::ztd::out_ptr; }
12+
#endif
13+
// clang-format on

libraries/core/tests/conformance/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
target_sources(MorpheusCoreTests
22
PRIVATE
33
date.tests.cpp
4+
outptr.tests.cpp
45
print.tests.cpp
56
scan.tests.cpp
67
stacktrace.tests.cpp
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include "morpheus/core/conformance/outptr.hpp"
2+
3+
#include <catch2/catch_test_macros.hpp>
4+
#include <cstdlib>
5+
#include <memory>
6+
7+
// Dummy C-style API
8+
extern "C" {
9+
struct CObject
10+
{
11+
int value;
12+
};
13+
14+
// Allocate a new object
15+
void create_object(CObject** obj)
16+
{
17+
*obj = static_cast<CObject*>(std::malloc(sizeof(CObject)));
18+
(*obj)->value = 42;
19+
}
20+
21+
// Modify an existing object, reallocating if necessary
22+
void update_object(CObject** obj, int new_value)
23+
{
24+
if (!*obj)
25+
{
26+
*obj = static_cast<CObject*>(std::malloc(sizeof(CObject)));
27+
}
28+
(*obj)->value = new_value;
29+
}
30+
31+
// Free an object
32+
void destroy_object(CObject* obj)
33+
{
34+
std::free(obj);
35+
}
36+
}
37+
38+
namespace morpheus
39+
{
40+
41+
TEST_CASE("std::out_ptr works for initial ownership acquisition", "[morpheus.conformance.outptr]")
42+
{
43+
std::unique_ptr<CObject, decltype(&destroy_object)> ptr(nullptr, &destroy_object);
44+
45+
// Acquire ownership from a raw C API using out_ptr
46+
create_object(conf::ptr::out_ptr(ptr));
47+
48+
REQUIRE(ptr != nullptr);
49+
REQUIRE(ptr->value == 42);
50+
}
51+
52+
TEST_CASE("std::inout_ptr works for modifying existing allocation", "[morpheus.conformance.inoutptr]")
53+
{
54+
std::unique_ptr<CObject, decltype(&destroy_object)> ptr(nullptr, &destroy_object);
55+
56+
// First allocate
57+
create_object(conf::ptr::out_ptr(ptr));
58+
REQUIRE(ptr->value == 42);
59+
60+
ptr.release();
61+
REQUIRE(ptr == nullptr);
62+
63+
update_object(conf::ptr::out_ptr(ptr), 64);
64+
REQUIRE(ptr != nullptr);
65+
REQUIRE(ptr->value == 64);
66+
67+
// Now update the existing object with a new value using inout_ptr
68+
update_object(conf::ptr::inout_ptr(ptr), 99);
69+
REQUIRE(ptr != nullptr);
70+
REQUIRE(ptr->value == 99);
71+
}
72+
73+
} // namespace morpheus

0 commit comments

Comments
 (0)