49template <
class T, std::size_t Size, std::size_t Alignment,
bool Strict =
false>
50class FastPimpl final {
53 USERVER_IMPL_NODEBUG_INLINE_FUNC FastPimpl(FastPimpl&& v)
noexcept(
noexcept(T(std::declval<T>())))
54 : FastPimpl(std::move(*v))
58 USERVER_IMPL_NODEBUG_INLINE_FUNC FastPimpl(
const FastPimpl& v)
noexcept(
noexcept(T(std::declval<
const T&>())))
63 USERVER_IMPL_NODEBUG_INLINE_FUNC FastPimpl& operator=(
const FastPimpl& rhs
64 )
noexcept(
noexcept(std::declval<T&>() = std::declval<
const T&>())) {
69 USERVER_IMPL_NODEBUG_INLINE_FUNC FastPimpl& operator=(FastPimpl&& rhs)
noexcept(
71 noexcept(std::declval<T&>() = std::declval<T>())
73 *AsHeld() = std::move(*rhs);
77 template <
typename... Args>
79 USERVER_IMPL_NODEBUG_INLINE_FUNC
explicit FastPimpl(Args&&... args)
noexcept(
noexcept(T(std::declval<Args>()...))) {
80 ::
new (AsHeld()) T(std::forward<Args>(args)...);
83 USERVER_IMPL_NODEBUG_INLINE_FUNC T* operator->()
noexcept USERVER_IMPL_LIFETIME_BOUND {
return AsHeld(); }
85 USERVER_IMPL_NODEBUG_INLINE_FUNC
const T* operator->()
const noexcept USERVER_IMPL_LIFETIME_BOUND {
89 USERVER_IMPL_NODEBUG_INLINE_FUNC T& operator*()
noexcept USERVER_IMPL_LIFETIME_BOUND {
return *AsHeld(); }
91 USERVER_IMPL_NODEBUG_INLINE_FUNC
const T& operator*()
const noexcept USERVER_IMPL_LIFETIME_BOUND {
95 USERVER_IMPL_NODEBUG_INLINE_FUNC ~FastPimpl()
noexcept {
96 Validate<
sizeof(T),
alignof(T),
noexcept(std::declval<T*>()->~T())>();
97 std::destroy_at(AsHeld());
102 template <std::size_t ActualSize, std::size_t ActualAlignment,
bool ActualNoexcept>
103 USERVER_IMPL_NODEBUG_INLINE_FUNC
static void Validate()
noexcept {
104 static_assert(Size >= ActualSize,
"invalid Size: Size >= sizeof(T) failed");
105 static_assert(!Strict || Size == ActualSize,
"invalid Size: Size == sizeof(T) failed");
107 static_assert(Alignment % ActualAlignment == 0,
"invalid Alignment: Alignment % alignof(T) == 0 failed");
108 static_assert(!Strict || Alignment == ActualAlignment,
"invalid Alignment: Alignment == alignof(T) failed");
110 static_assert(ActualNoexcept,
"Destructor of FastPimpl is marked as noexcept, the ~T() is not");
113 alignas(Alignment) std::byte storage_[Size];
115 USERVER_IMPL_NODEBUG_INLINE_FUNC T* AsHeld()
noexcept {
return reinterpret_cast<T*>(&storage_); }
117 USERVER_IMPL_NODEBUG_INLINE_FUNC
const T* AsHeld()
const noexcept {
return reinterpret_cast<
const T*>(&storage_); }