From 21f34bd99c0403b34ae9301e309ef3430682827e Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sun, 27 Feb 2022 18:30:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8=E5=8F=AF=E8=83=BD=E7=9A=84=E6=83=85?= =?UTF-8?q?=E5=86=B5=E4=B8=8B=E4=BD=BF=E7=94=A8std=E7=9A=84construct=5Fat/?= =?UTF-8?q?destroy=5Fat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libipc/utility/construct.h | 33 +++++++++++++++++++++++++++++++++ test/test_utility.cpp | 17 +++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/libipc/utility/construct.h b/src/libipc/utility/construct.h index 1cf7f3a..ad21ffd 100644 --- a/src/libipc/utility/construct.h +++ b/src/libipc/utility/construct.h @@ -9,15 +9,27 @@ #include // placement-new #include // std::enable_if_t #include // std::forward +#include // std::construct_at, std::destroy_at, std::addressof +#include #include "libipc/def.h" +#include "libipc/detect_plat.h" LIBIPC_NAMESPACE_BEG_ +/** + * @brief Creates an object at a given address, like 'construct_at' in c++20 + * @see https://en.cppreference.com/w/cpp/memory/construct_at +*/ + template auto construct(void *p, A &&... args) -> std::enable_if_t<::std::is_constructible::value, T *> { +#if defined(LIBIPC_CPP_20) + return std::construct_at(static_cast(p), std::forward(args)...); +#else return ::new (p) T(std::forward(args)...); +#endif } template @@ -26,9 +38,30 @@ auto construct(void *p, A &&... args) return ::new (p) T{std::forward(args)...}; } +/** + * @brief Destroys an object at a given address, like 'destroy_at' in c++17 + * @see https://en.cppreference.com/w/cpp/memory/destroy_at +*/ + template void *destroy(T *p) noexcept { +#if defined(LIBIPC_CPP_17) + std::destroy_at(p); +#else p->~T(); +#endif + return p; +} + +template +void *destroy(T (*p)[N]) noexcept { +#if defined(LIBIPC_CPP_20) + std::destroy_at(p); +#elif defined(LIBIPC_CPP_17) + std::destroy(std::begin(*p), std::end(*p)); +#else + for (auto &elem : *p) destroy(std::addressof(elem)); +#endif return p; } diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 4d6e7d8..8d3751e 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -18,16 +18,33 @@ TEST(utility, construct) { EXPECT_EQ(pfoo->a_, 123); EXPECT_EQ(pfoo->b_, 321); EXPECT_EQ(pfoo->c_, '1'); + ipc::destroy(pfoo); struct Bar : Foo { Bar(int a, short b, char c) : Foo{a, b, c} {} + ~Bar() { a_ = 0; } }; std::aligned_storage_t bar; Bar *pbar = ipc::construct(&bar, 123, short(321), '1'); EXPECT_EQ(pbar->a_, 123); EXPECT_EQ(pbar->b_, 321); EXPECT_EQ(pbar->c_, '1'); + ipc::destroy(pbar); + EXPECT_EQ(pbar->a_, 0); + + std::aligned_storage_t bars[3]; + for (auto &b : bars) { + auto pb = ipc::construct(&b, 321, short(123), '3'); + EXPECT_EQ(pb->a_, 321); + EXPECT_EQ(pb->b_, 123); + EXPECT_EQ(pb->c_, '3'); + } + ipc::destroy(reinterpret_cast(&bars)); + for (auto &b : bars) { + auto pb = reinterpret_cast(&b); + EXPECT_EQ(pb->a_, 0); + } } namespace {