From e8b49c5105bd1d5ca99c18217c442aa67ab293da Mon Sep 17 00:00:00 2001 From: wokron Date: Fri, 3 Apr 2026 14:36:38 +0800 Subject: [PATCH 1/4] enhance RawStorage class --- include/condy/utils.hpp | 12 +++++++++--- tests/test_utils.cpp | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/condy/utils.hpp b/include/condy/utils.hpp index fbaf55c2..ab55315f 100644 --- a/include/condy/utils.hpp +++ b/include/condy/utils.hpp @@ -82,16 +82,22 @@ template auto defer(Func &&func) { template class RawStorage { public: + template + void accept(Factory &&factory) noexcept( + std::is_nothrow_invocable_r_v) { + new (&storage_) T(std::forward(factory)()); + } + template void construct(Args &&...args) noexcept( std::is_nothrow_constructible_v) { - new (&storage_) T(std::forward(args)...); + accept([&]() { return T(std::forward(args)...); }); } - T &get() noexcept { return *reinterpret_cast(&storage_); } + T &get() noexcept { return *std::launder(reinterpret_cast(storage_)); } const T &get() const noexcept { - return *reinterpret_cast(&storage_); + return *std::launder(reinterpret_cast(storage_)); } void destroy() noexcept { get().~T(); } diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index 2296a867..d901a4a7 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -42,6 +42,26 @@ TEST_CASE("test raw_storage - std::unique_ptr") { REQUIRE(int_deleter::called); } +TEST_CASE("test raw_storage - guaranteed return value optimization") { + struct Fixed { + Fixed(int v) : value(v) {} + Fixed(const Fixed &) = delete; + Fixed &operator=(const Fixed &) = delete; + Fixed(Fixed &&) = delete; + Fixed &operator=(Fixed &&) = delete; + int value; + }; + + auto f1 = [](int v) { return Fixed(v); }; + + auto f2 = [&]() { return f1(42); }; + + condy::RawStorage storage; + storage.accept(f2); + REQUIRE(storage.get().value == 42); + storage.destroy(); +} + TEST_CASE("test small_array - small") { condy::SmallArray arr(3); arr[0] = 10; From a593799f91df051faf9fb5d7fb46ea2b49da2143 Mon Sep 17 00:00:00 2001 From: wokron Date: Fri, 3 Apr 2026 14:45:23 +0800 Subject: [PATCH 2/4] fix wrong test --- tests/test_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index d901a4a7..768993f5 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -19,7 +19,7 @@ struct int_deleter { TEST_CASE("test raw_storage - int") { condy::RawStorage storage; - new (&storage) int(77); + storage.construct(77); REQUIRE(storage.get() == 77); storage.destroy(); } From 726013c1acad1062ac9664a3ab0f3622710a6ef2 Mon Sep 17 00:00:00 2001 From: wokron Date: Fri, 3 Apr 2026 14:47:52 +0800 Subject: [PATCH 3/4] coro custom allocator use launder as well --- include/condy/coro.inl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/condy/coro.inl b/include/condy/coro.inl index 6bab1940..24d5d043 100644 --- a/include/condy/coro.inl +++ b/include/condy/coro.inl @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace condy { @@ -64,8 +65,8 @@ public: (size + alignof(Allocator) - 1) & ~(alignof(Allocator) - 1); size_t total_size = allocator_offset + sizeof(Allocator); Pointer mem = static_cast(ptr); - Allocator &alloc = - *reinterpret_cast(mem + allocator_offset); + Allocator &alloc = *std::launder( + reinterpret_cast(mem + allocator_offset)); Allocator alloc_copy = std::move(alloc); alloc.~Allocator(); alloc_copy.deallocate(mem, total_size); From d452431b1255ee004003771a6e9f964e53bef495 Mon Sep 17 00:00:00 2001 From: wokron Date: Fri, 3 Apr 2026 19:26:36 +0800 Subject: [PATCH 4/4] minor change --- include/condy/utils.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/condy/utils.hpp b/include/condy/utils.hpp index ab55315f..dcfc0015 100644 --- a/include/condy/utils.hpp +++ b/include/condy/utils.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -84,7 +85,7 @@ template class RawStorage { public: template void accept(Factory &&factory) noexcept( - std::is_nothrow_invocable_r_v) { + noexcept(T(std::forward(factory)()))) { new (&storage_) T(std::forward(factory)()); }