mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
在可能的情况下使用std的construct_at/destroy_at
This commit is contained in:
parent
c54e052838
commit
21f34bd99c
@ -9,15 +9,27 @@
|
||||
#include <new> // placement-new
|
||||
#include <type_traits> // std::enable_if_t
|
||||
#include <utility> // std::forward
|
||||
#include <memory> // std::construct_at, std::destroy_at, std::addressof
|
||||
#include <cstddef>
|
||||
|
||||
#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 <typename T, typename... A>
|
||||
auto construct(void *p, A &&... args)
|
||||
-> std::enable_if_t<::std::is_constructible<T, A...>::value, T *> {
|
||||
#if defined(LIBIPC_CPP_20)
|
||||
return std::construct_at(static_cast<T *>(p), std::forward<A>(args)...);
|
||||
#else
|
||||
return ::new (p) T(std::forward<A>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T, typename... A>
|
||||
@ -26,9 +38,30 @@ auto construct(void *p, A &&... args)
|
||||
return ::new (p) T{std::forward<A>(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 <typename T>
|
||||
void *destroy(T *p) noexcept {
|
||||
#if defined(LIBIPC_CPP_17)
|
||||
std::destroy_at(p);
|
||||
#else
|
||||
p->~T();
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<sizeof(Bar)> bar;
|
||||
Bar *pbar = ipc::construct<Bar>(&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<sizeof(Bar)> bars[3];
|
||||
for (auto &b : bars) {
|
||||
auto pb = ipc::construct<Bar>(&b, 321, short(123), '3');
|
||||
EXPECT_EQ(pb->a_, 321);
|
||||
EXPECT_EQ(pb->b_, 123);
|
||||
EXPECT_EQ(pb->c_, '3');
|
||||
}
|
||||
ipc::destroy(reinterpret_cast<Bar(*)[3]>(&bars));
|
||||
for (auto &b : bars) {
|
||||
auto pb = reinterpret_cast<Bar *>(&b);
|
||||
EXPECT_EQ(pb->a_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user