mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 03:45:30 +07:00
remove deprecated std::aligned_storage usage (github issue #17)
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <new>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|||||||
@@ -9,16 +9,17 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <new>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename Function, std::size_t MaxFunctorSize = sizeof(void*) * 2 >
|
template < typename Function >
|
||||||
class fixed_function;
|
class fixed_function;
|
||||||
|
|
||||||
template < typename R, typename... Args, std::size_t MaxFunctorSize >
|
template < typename R, typename... Args >
|
||||||
class fixed_function<R(Args...), MaxFunctorSize> final {
|
class fixed_function<R(Args...)> final {
|
||||||
public:
|
public:
|
||||||
using result_type = R;
|
using result_type = R;
|
||||||
|
|
||||||
@@ -78,59 +79,62 @@ namespace meta_hpp::detail
|
|||||||
struct vtable_t;
|
struct vtable_t;
|
||||||
vtable_t* vtable_{};
|
vtable_t* vtable_{};
|
||||||
private:
|
private:
|
||||||
using storage_t = std::aligned_storage_t<MaxFunctorSize>;
|
struct buffer_t final {
|
||||||
storage_t storage_{};
|
// NOLINTNEXTLINE(*-avoid-c-arrays)
|
||||||
|
alignas(std::max_align_t) std::byte data[sizeof(void*) * 2];
|
||||||
|
} buffer_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
template < typename Function, std::size_t MaxFunctorSize >
|
template < typename Function >
|
||||||
inline void swap(fixed_function<Function, MaxFunctorSize>& l, fixed_function<Function, MaxFunctorSize>& r) noexcept {
|
inline void swap(fixed_function<Function>& l, fixed_function<Function>& r) noexcept {
|
||||||
l.swap(r);
|
l.swap(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename R, typename... Args, std::size_t MaxFunctorSize >
|
template < typename R, typename... Args >
|
||||||
struct fixed_function<R(Args...), MaxFunctorSize>::vtable_t final {
|
struct fixed_function<R(Args...)>::vtable_t final {
|
||||||
R (*const call)(const fixed_function& self, Args... args);
|
R (*const call)(const fixed_function& self, Args... args);
|
||||||
void (*const move)(fixed_function& from, fixed_function& to) noexcept;
|
void (*const move)(fixed_function& from, fixed_function& to) noexcept;
|
||||||
void (*const destroy)(fixed_function& self);
|
void (*const destroy)(fixed_function& self);
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
static T* storage_cast(storage_t& storage) noexcept {
|
static T* buffer_cast(buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<T*>(&storage);
|
return std::launder(reinterpret_cast<T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
static const T* storage_cast(const storage_t& storage) noexcept {
|
static const T* buffer_cast(const buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<const T*>(&storage);
|
return std::launder(reinterpret_cast<const T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename FunctionType >
|
template < typename Fp >
|
||||||
static vtable_t* get() {
|
static vtable_t* get() {
|
||||||
static vtable_t table{
|
static vtable_t table{
|
||||||
.call = +[](const fixed_function& self, Args... args) -> R {
|
.call = +[](const fixed_function& self, Args... args) -> R {
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
const FunctionType& src = *storage_cast<FunctionType>(self.storage_);
|
const Fp& src = *buffer_cast<Fp>(self.buffer_);
|
||||||
return std::invoke(src, std::forward<Args>(args)...);
|
return std::invoke(src, std::forward<Args>(args)...);
|
||||||
},
|
},
|
||||||
.move = +[](fixed_function& from, fixed_function& to) noexcept {
|
.move = +[](fixed_function& from, fixed_function& to) noexcept {
|
||||||
assert(from && !to);
|
assert(from && !to);
|
||||||
|
|
||||||
FunctionType& src = *storage_cast<FunctionType>(from.storage_);
|
Fp& src = *buffer_cast<Fp>(from.buffer_);
|
||||||
::new (&to.storage_) FunctionType(std::move(src));
|
::new (buffer_cast<Fp>(to.buffer_)) Fp(std::move(src));
|
||||||
|
src.~Fp();
|
||||||
|
|
||||||
to.vtable_ = from.vtable_;
|
to.vtable_ = from.vtable_;
|
||||||
from.vtable_->destroy(from);
|
from.vtable_ = nullptr;
|
||||||
},
|
},
|
||||||
.destroy = +[](fixed_function& self){
|
.destroy = +[](fixed_function& self){
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
FunctionType& src = *storage_cast<FunctionType>(self.storage_);
|
Fp& src = *buffer_cast<Fp>(self.buffer_);
|
||||||
src.~FunctionType();
|
src.~Fp();
|
||||||
|
|
||||||
self.vtable_ = nullptr;
|
self.vtable_ = nullptr;
|
||||||
},
|
},
|
||||||
@@ -142,12 +146,13 @@ namespace meta_hpp::detail
|
|||||||
static void construct(fixed_function& dst, Functor&& functor) {
|
static void construct(fixed_function& dst, Functor&& functor) {
|
||||||
using Fp = std::decay_t<Functor>;
|
using Fp = std::decay_t<Functor>;
|
||||||
|
|
||||||
static_assert(sizeof(Fp) <= MaxFunctorSize);
|
static_assert(sizeof(Fp) <= sizeof(buffer_t));
|
||||||
static_assert(alignof(Fp) <= alignof(storage_t));
|
static_assert(alignof(Fp) <= alignof(buffer_t));
|
||||||
static_assert(std::is_invocable_r_v<R, Fp, Args...>);
|
static_assert(std::is_invocable_r_v<R, Fp, Args...>);
|
||||||
static_assert(std::is_nothrow_move_constructible_v<Fp>);
|
static_assert(std::is_nothrow_move_constructible_v<Fp>);
|
||||||
|
|
||||||
::new (&dst.storage_) Fp(std::forward<Functor>(functor));
|
::new (buffer_cast<Fp>(dst.buffer_)) Fp(std::forward<Functor>(functor));
|
||||||
|
|
||||||
dst.vtable_ = vtable_t::get<Fp>();
|
dst.vtable_ = vtable_t::get<Fp>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,10 @@ namespace meta_hpp
|
|||||||
struct vtable_t;
|
struct vtable_t;
|
||||||
vtable_t* vtable_{};
|
vtable_t* vtable_{};
|
||||||
private:
|
private:
|
||||||
using buffer_t = std::aligned_storage_t<sizeof(void*) * 2>;
|
struct buffer_t final {
|
||||||
|
// NOLINTNEXTLINE(*-avoid-c-arrays)
|
||||||
|
alignas(std::max_align_t) std::byte data[sizeof(void*) * 2];
|
||||||
|
};
|
||||||
using storage_u = std::variant<std::monostate, void*, buffer_t>;
|
using storage_u = std::variant<std::monostate, void*, buffer_t>;
|
||||||
storage_u storage_{};
|
storage_u storage_{};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ namespace meta_hpp
|
|||||||
template < typename T >
|
template < typename T >
|
||||||
static T* buffer_cast(buffer_t& buffer) noexcept {
|
static T* buffer_cast(buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<T*>(&buffer);
|
return std::launder(reinterpret_cast<T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
static const T* buffer_cast(const buffer_t& buffer) noexcept {
|
static const T* buffer_cast(const buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<const T*>(&buffer);
|
return std::launder(reinterpret_cast<const T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -78,8 +78,7 @@ namespace meta_hpp
|
|||||||
std::is_nothrow_move_constructible_v<Tp>;
|
std::is_nothrow_move_constructible_v<Tp>;
|
||||||
|
|
||||||
if constexpr ( in_buffer ) {
|
if constexpr ( in_buffer ) {
|
||||||
dst.storage_.emplace<buffer_t>();
|
::new (buffer_cast<Tp>(dst.storage_.emplace<buffer_t>())) Tp(std::forward<T>(val));
|
||||||
::new (storage_cast<Tp>(dst.storage_)) Tp(std::forward<T>(val));
|
|
||||||
} else {
|
} else {
|
||||||
dst.storage_.emplace<void*>(std::make_unique<Tp>(std::forward<T>(val)).release());
|
dst.storage_.emplace<void*>(std::make_unique<Tp>(std::forward<T>(val)).release());
|
||||||
}
|
}
|
||||||
@@ -137,7 +136,7 @@ namespace meta_hpp
|
|||||||
},
|
},
|
||||||
[&to](buffer_t& buffer) {
|
[&to](buffer_t& buffer) {
|
||||||
Tp& src = *buffer_cast<Tp>(buffer);
|
Tp& src = *buffer_cast<Tp>(buffer);
|
||||||
::new (&to.storage_.emplace<buffer_t>()) Tp(std::move(src));
|
::new (buffer_cast<Tp>(to.storage_.emplace<buffer_t>())) Tp(std::move(src));
|
||||||
src.~Tp();
|
src.~Tp();
|
||||||
},
|
},
|
||||||
[](...){}
|
[](...){}
|
||||||
@@ -153,11 +152,11 @@ namespace meta_hpp
|
|||||||
std::visit(detail::overloaded {
|
std::visit(detail::overloaded {
|
||||||
[&to](void* ptr) {
|
[&to](void* ptr) {
|
||||||
const Tp& src = *static_cast<const Tp*>(ptr);
|
const Tp& src = *static_cast<const Tp*>(ptr);
|
||||||
to.storage_.emplace<void*>(new Tp(src));
|
to.storage_.emplace<void*>(std::make_unique<Tp>(src).release());
|
||||||
},
|
},
|
||||||
[&to](const buffer_t& buffer) {
|
[&to](const buffer_t& buffer) {
|
||||||
const Tp& src = *buffer_cast<Tp>(buffer);
|
const Tp& src = *buffer_cast<Tp>(buffer);
|
||||||
::new (&to.storage_.emplace<buffer_t>()) Tp(src);
|
::new (buffer_cast<Tp>(to.storage_.emplace<buffer_t>())) Tp(src);
|
||||||
},
|
},
|
||||||
[](...){}
|
[](...){}
|
||||||
}, from.storage_);
|
}, from.storage_);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <new>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -223,11 +224,11 @@ namespace meta_hpp::detail
|
|||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename Function, std::size_t MaxFunctorSize = sizeof(void*) * 2 >
|
template < typename Function >
|
||||||
class fixed_function;
|
class fixed_function;
|
||||||
|
|
||||||
template < typename R, typename... Args, std::size_t MaxFunctorSize >
|
template < typename R, typename... Args >
|
||||||
class fixed_function<R(Args...), MaxFunctorSize> final {
|
class fixed_function<R(Args...)> final {
|
||||||
public:
|
public:
|
||||||
using result_type = R;
|
using result_type = R;
|
||||||
|
|
||||||
@@ -287,59 +288,62 @@ namespace meta_hpp::detail
|
|||||||
struct vtable_t;
|
struct vtable_t;
|
||||||
vtable_t* vtable_{};
|
vtable_t* vtable_{};
|
||||||
private:
|
private:
|
||||||
using storage_t = std::aligned_storage_t<MaxFunctorSize>;
|
struct buffer_t final {
|
||||||
storage_t storage_{};
|
// NOLINTNEXTLINE(*-avoid-c-arrays)
|
||||||
|
alignas(std::max_align_t) std::byte data[sizeof(void*) * 2];
|
||||||
|
} buffer_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
template < typename Function, std::size_t MaxFunctorSize >
|
template < typename Function >
|
||||||
inline void swap(fixed_function<Function, MaxFunctorSize>& l, fixed_function<Function, MaxFunctorSize>& r) noexcept {
|
inline void swap(fixed_function<Function>& l, fixed_function<Function>& r) noexcept {
|
||||||
l.swap(r);
|
l.swap(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename R, typename... Args, std::size_t MaxFunctorSize >
|
template < typename R, typename... Args >
|
||||||
struct fixed_function<R(Args...), MaxFunctorSize>::vtable_t final {
|
struct fixed_function<R(Args...)>::vtable_t final {
|
||||||
R (*const call)(const fixed_function& self, Args... args);
|
R (*const call)(const fixed_function& self, Args... args);
|
||||||
void (*const move)(fixed_function& from, fixed_function& to) noexcept;
|
void (*const move)(fixed_function& from, fixed_function& to) noexcept;
|
||||||
void (*const destroy)(fixed_function& self);
|
void (*const destroy)(fixed_function& self);
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
static T* storage_cast(storage_t& storage) noexcept {
|
static T* buffer_cast(buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<T*>(&storage);
|
return std::launder(reinterpret_cast<T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
static const T* storage_cast(const storage_t& storage) noexcept {
|
static const T* buffer_cast(const buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<const T*>(&storage);
|
return std::launder(reinterpret_cast<const T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename FunctionType >
|
template < typename Fp >
|
||||||
static vtable_t* get() {
|
static vtable_t* get() {
|
||||||
static vtable_t table{
|
static vtable_t table{
|
||||||
.call = +[](const fixed_function& self, Args... args) -> R {
|
.call = +[](const fixed_function& self, Args... args) -> R {
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
const FunctionType& src = *storage_cast<FunctionType>(self.storage_);
|
const Fp& src = *buffer_cast<Fp>(self.buffer_);
|
||||||
return std::invoke(src, std::forward<Args>(args)...);
|
return std::invoke(src, std::forward<Args>(args)...);
|
||||||
},
|
},
|
||||||
.move = +[](fixed_function& from, fixed_function& to) noexcept {
|
.move = +[](fixed_function& from, fixed_function& to) noexcept {
|
||||||
assert(from && !to);
|
assert(from && !to);
|
||||||
|
|
||||||
FunctionType& src = *storage_cast<FunctionType>(from.storage_);
|
Fp& src = *buffer_cast<Fp>(from.buffer_);
|
||||||
::new (&to.storage_) FunctionType(std::move(src));
|
::new (buffer_cast<Fp>(to.buffer_)) Fp(std::move(src));
|
||||||
|
src.~Fp();
|
||||||
|
|
||||||
to.vtable_ = from.vtable_;
|
to.vtable_ = from.vtable_;
|
||||||
from.vtable_->destroy(from);
|
from.vtable_ = nullptr;
|
||||||
},
|
},
|
||||||
.destroy = +[](fixed_function& self){
|
.destroy = +[](fixed_function& self){
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
FunctionType& src = *storage_cast<FunctionType>(self.storage_);
|
Fp& src = *buffer_cast<Fp>(self.buffer_);
|
||||||
src.~FunctionType();
|
src.~Fp();
|
||||||
|
|
||||||
self.vtable_ = nullptr;
|
self.vtable_ = nullptr;
|
||||||
},
|
},
|
||||||
@@ -351,12 +355,13 @@ namespace meta_hpp::detail
|
|||||||
static void construct(fixed_function& dst, Functor&& functor) {
|
static void construct(fixed_function& dst, Functor&& functor) {
|
||||||
using Fp = std::decay_t<Functor>;
|
using Fp = std::decay_t<Functor>;
|
||||||
|
|
||||||
static_assert(sizeof(Fp) <= MaxFunctorSize);
|
static_assert(sizeof(Fp) <= sizeof(buffer_t));
|
||||||
static_assert(alignof(Fp) <= alignof(storage_t));
|
static_assert(alignof(Fp) <= alignof(buffer_t));
|
||||||
static_assert(std::is_invocable_r_v<R, Fp, Args...>);
|
static_assert(std::is_invocable_r_v<R, Fp, Args...>);
|
||||||
static_assert(std::is_nothrow_move_constructible_v<Fp>);
|
static_assert(std::is_nothrow_move_constructible_v<Fp>);
|
||||||
|
|
||||||
::new (&dst.storage_) Fp(std::forward<Functor>(functor));
|
::new (buffer_cast<Fp>(dst.buffer_)) Fp(std::forward<Functor>(functor));
|
||||||
|
|
||||||
dst.vtable_ = vtable_t::get<Fp>();
|
dst.vtable_ = vtable_t::get<Fp>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2235,7 +2240,10 @@ namespace meta_hpp
|
|||||||
struct vtable_t;
|
struct vtable_t;
|
||||||
vtable_t* vtable_{};
|
vtable_t* vtable_{};
|
||||||
private:
|
private:
|
||||||
using buffer_t = std::aligned_storage_t<sizeof(void*) * 2>;
|
struct buffer_t final {
|
||||||
|
// NOLINTNEXTLINE(*-avoid-c-arrays)
|
||||||
|
alignas(std::max_align_t) std::byte data[sizeof(void*) * 2];
|
||||||
|
};
|
||||||
using storage_u = std::variant<std::monostate, void*, buffer_t>;
|
using storage_u = std::variant<std::monostate, void*, buffer_t>;
|
||||||
storage_u storage_{};
|
storage_u storage_{};
|
||||||
};
|
};
|
||||||
@@ -7968,13 +7976,13 @@ namespace meta_hpp
|
|||||||
template < typename T >
|
template < typename T >
|
||||||
static T* buffer_cast(buffer_t& buffer) noexcept {
|
static T* buffer_cast(buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<T*>(&buffer);
|
return std::launder(reinterpret_cast<T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
static const T* buffer_cast(const buffer_t& buffer) noexcept {
|
static const T* buffer_cast(const buffer_t& buffer) noexcept {
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
return reinterpret_cast<const T*>(&buffer);
|
return std::launder(reinterpret_cast<const T*>(buffer.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -8005,8 +8013,7 @@ namespace meta_hpp
|
|||||||
std::is_nothrow_move_constructible_v<Tp>;
|
std::is_nothrow_move_constructible_v<Tp>;
|
||||||
|
|
||||||
if constexpr ( in_buffer ) {
|
if constexpr ( in_buffer ) {
|
||||||
dst.storage_.emplace<buffer_t>();
|
::new (buffer_cast<Tp>(dst.storage_.emplace<buffer_t>())) Tp(std::forward<T>(val));
|
||||||
::new (storage_cast<Tp>(dst.storage_)) Tp(std::forward<T>(val));
|
|
||||||
} else {
|
} else {
|
||||||
dst.storage_.emplace<void*>(std::make_unique<Tp>(std::forward<T>(val)).release());
|
dst.storage_.emplace<void*>(std::make_unique<Tp>(std::forward<T>(val)).release());
|
||||||
}
|
}
|
||||||
@@ -8064,7 +8071,7 @@ namespace meta_hpp
|
|||||||
},
|
},
|
||||||
[&to](buffer_t& buffer) {
|
[&to](buffer_t& buffer) {
|
||||||
Tp& src = *buffer_cast<Tp>(buffer);
|
Tp& src = *buffer_cast<Tp>(buffer);
|
||||||
::new (&to.storage_.emplace<buffer_t>()) Tp(std::move(src));
|
::new (buffer_cast<Tp>(to.storage_.emplace<buffer_t>())) Tp(std::move(src));
|
||||||
src.~Tp();
|
src.~Tp();
|
||||||
},
|
},
|
||||||
[](...){}
|
[](...){}
|
||||||
@@ -8080,11 +8087,11 @@ namespace meta_hpp
|
|||||||
std::visit(detail::overloaded {
|
std::visit(detail::overloaded {
|
||||||
[&to](void* ptr) {
|
[&to](void* ptr) {
|
||||||
const Tp& src = *static_cast<const Tp*>(ptr);
|
const Tp& src = *static_cast<const Tp*>(ptr);
|
||||||
to.storage_.emplace<void*>(new Tp(src));
|
to.storage_.emplace<void*>(std::make_unique<Tp>(src).release());
|
||||||
},
|
},
|
||||||
[&to](const buffer_t& buffer) {
|
[&to](const buffer_t& buffer) {
|
||||||
const Tp& src = *buffer_cast<Tp>(buffer);
|
const Tp& src = *buffer_cast<Tp>(buffer);
|
||||||
::new (&to.storage_.emplace<buffer_t>()) Tp(src);
|
::new (buffer_cast<Tp>(to.storage_.emplace<buffer_t>())) Tp(src);
|
||||||
},
|
},
|
||||||
[](...){}
|
[](...){}
|
||||||
}, from.storage_);
|
}, from.storage_);
|
||||||
|
|||||||
Reference in New Issue
Block a user