capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

memory.h (20927B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #pragma once
     23 
     24 #include "common.h"
     25 
     26 KJ_BEGIN_HEADER
     27 
     28 namespace kj {
     29 
     30 template <typename T>
     31 inline constexpr bool _kj_internal_isPolymorphic(T*) {
     32   // If you get a compiler error here complaining that T is incomplete, it's because you are trying
     33   // to use kj::Own<T> with a type that has only been forward-declared. Since KJ doesn't know if
     34   // the type might be involved in inheritance (especially multiple inheritance), it doesn't know
     35   // how to correctly call the disposer to destroy the type, since the object's true memory address
     36   // may differ from the address used to point to a superclass.
     37   //
     38   // However, if you know for sure that T is NOT polymorphic (i.e. it doesn't have a vtable and
     39   // isn't involved in inheritance), then you can use KJ_DECLARE_NON_POLYMORPHIC(T) to declare this
     40   // to KJ without actually completing the type. Place this macro invocation either in the global
     41   // scope, or in the same namespace as T is defined.
     42   return __is_polymorphic(T);
     43 }
     44 
     45 #define KJ_DECLARE_NON_POLYMORPHIC(...) \
     46   inline constexpr bool _kj_internal_isPolymorphic(__VA_ARGS__*) { \
     47     return false; \
     48   }
     49 // If you want to use kj::Own<T> for an incomplete type T that you know is not polymorphic, then
     50 // write `KJ_DECLARE_NON_POLYMORPHIC(T)` either at the global scope or in the same namespace as
     51 // T is declared.
     52 //
     53 // This also works for templates, e.g.:
     54 //
     55 //     template <typename X, typename Y>
     56 //     struct MyType;
     57 //     template <typename X, typename Y>
     58 //     KJ_DECLARE_NON_POLYMORPHIC(MyType<X, Y>)
     59 
     60 namespace _ {  // private
     61 
     62 template <typename T> struct RefOrVoid_ { typedef T& Type; };
     63 template <> struct RefOrVoid_<void> { typedef void Type; };
     64 template <> struct RefOrVoid_<const void> { typedef void Type; };
     65 
     66 template <typename T>
     67 using RefOrVoid = typename RefOrVoid_<T>::Type;
     68 // Evaluates to T&, unless T is `void`, in which case evaluates to `void`.
     69 //
     70 // This is a hack needed to avoid defining Own<void> as a totally separate class.
     71 
     72 template <typename T, bool isPolymorphic = _kj_internal_isPolymorphic((T*)nullptr)>
     73 struct CastToVoid_;
     74 
     75 template <typename T>
     76 struct CastToVoid_<T, false> {
     77   static void* apply(T* ptr) {
     78     return static_cast<void*>(ptr);
     79   }
     80   static const void* applyConst(T* ptr) {
     81     const T* cptr = ptr;
     82     return static_cast<const void*>(cptr);
     83   }
     84 };
     85 
     86 template <typename T>
     87 struct CastToVoid_<T, true> {
     88   static void* apply(T* ptr) {
     89     return dynamic_cast<void*>(ptr);
     90   }
     91   static const void* applyConst(T* ptr) {
     92     const T* cptr = ptr;
     93     return dynamic_cast<const void*>(cptr);
     94   }
     95 };
     96 
     97 template <typename T>
     98 void* castToVoid(T* ptr) {
     99   return CastToVoid_<T>::apply(ptr);
    100 }
    101 
    102 template <typename T>
    103 const void* castToConstVoid(T* ptr) {
    104   return CastToVoid_<T>::applyConst(ptr);
    105 }
    106 
    107 }  // namespace _ (private)
    108 
    109 // =======================================================================================
    110 // Disposer -- Implementation details.
    111 
    112 class Disposer {
    113   // Abstract interface for a thing that "disposes" of objects, where "disposing" usually means
    114   // calling the destructor followed by freeing the underlying memory.  `Own<T>` encapsulates an
    115   // object pointer with corresponding Disposer.
    116   //
    117   // Few developers will ever touch this interface.  It is primarily useful for those implementing
    118   // custom memory allocators.
    119 
    120 protected:
    121   // Do not declare a destructor, as doing so will force a global initializer for each HeapDisposer
    122   // instance.  Eww!
    123 
    124   virtual void disposeImpl(void* pointer) const = 0;
    125   // Disposes of the object, given a pointer to the beginning of the object.  If the object is
    126   // polymorphic, this pointer is determined by dynamic_cast<void*>().  For non-polymorphic types,
    127   // Own<T> does not allow any casting, so the pointer exactly matches the original one given to
    128   // Own<T>.
    129 
    130 public:
    131 
    132   template <typename T>
    133   void dispose(T* object) const;
    134   // Helper wrapper around disposeImpl().
    135   //
    136   // If T is polymorphic, calls `disposeImpl(dynamic_cast<void*>(object))`, otherwise calls
    137   // `disposeImpl(implicitCast<void*>(object))`.
    138   //
    139   // Callers must not call dispose() on the same pointer twice, even if the first call throws
    140   // an exception.
    141 
    142 private:
    143   template <typename T, bool polymorphic = _kj_internal_isPolymorphic((T*)nullptr)>
    144   struct Dispose_;
    145 };
    146 
    147 template <typename T>
    148 class DestructorOnlyDisposer: public Disposer {
    149   // A disposer that merely calls the type's destructor and nothing else.
    150 
    151 public:
    152   static const DestructorOnlyDisposer instance;
    153 
    154   void disposeImpl(void* pointer) const override {
    155     reinterpret_cast<T*>(pointer)->~T();
    156   }
    157 };
    158 
    159 template <typename T>
    160 const DestructorOnlyDisposer<T> DestructorOnlyDisposer<T>::instance = DestructorOnlyDisposer<T>();
    161 
    162 class NullDisposer: public Disposer {
    163   // A disposer that does nothing.
    164 
    165 public:
    166   static const NullDisposer instance;
    167 
    168   void disposeImpl(void* pointer) const override {}
    169 };
    170 
    171 // =======================================================================================
    172 // Own<T> -- An owned pointer.
    173 
    174 template <typename T>
    175 class Own {
    176   // A transferrable title to a T.  When an Own<T> goes out of scope, the object's Disposer is
    177   // called to dispose of it.  An Own<T> can be efficiently passed by move, without relocating the
    178   // underlying object; this transfers ownership.
    179   //
    180   // This is much like std::unique_ptr, except:
    181   // - You cannot release().  An owned object is not necessarily allocated with new (see next
    182   //   point), so it would be hard to use release() correctly.
    183   // - The deleter is made polymorphic by virtual call rather than by template.  This is much
    184   //   more powerful -- it allows the use of custom allocators, freelists, etc.  This could
    185   //   _almost_ be accomplished with unique_ptr by forcing everyone to use something like
    186   //   std::unique_ptr<T, kj::Deleter>, except that things get hairy in the presence of multiple
    187   //   inheritance and upcasting, and anyway if you force everyone to use a custom deleter
    188   //   then you've lost any benefit to interoperating with the "standard" unique_ptr.
    189 
    190 public:
    191   KJ_DISALLOW_COPY(Own);
    192   inline Own(): disposer(nullptr), ptr(nullptr) {}
    193   inline Own(Own&& other) noexcept
    194       : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
    195   inline Own(Own<RemoveConstOrDisable<T>>&& other) noexcept
    196       : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
    197   template <typename U, typename = EnableIf<canConvert<U*, T*>()>>
    198   inline Own(Own<U>&& other) noexcept
    199       : disposer(other.disposer), ptr(cast(other.ptr)) {
    200     other.ptr = nullptr;
    201   }
    202   inline Own(T* ptr, const Disposer& disposer) noexcept: disposer(&disposer), ptr(ptr) {}
    203 
    204   ~Own() noexcept(false) { dispose(); }
    205 
    206   inline Own& operator=(Own&& other) {
    207     // Move-assignnment operator.
    208 
    209     // Careful, this might own `other`.  Therefore we have to transfer the pointers first, then
    210     // dispose.
    211     const Disposer* disposerCopy = disposer;
    212     T* ptrCopy = ptr;
    213     disposer = other.disposer;
    214     ptr = other.ptr;
    215     other.ptr = nullptr;
    216     if (ptrCopy != nullptr) {
    217       disposerCopy->dispose(const_cast<RemoveConst<T>*>(ptrCopy));
    218     }
    219     return *this;
    220   }
    221 
    222   inline Own& operator=(decltype(nullptr)) {
    223     dispose();
    224     return *this;
    225   }
    226 
    227   template <typename... Attachments>
    228   Own<T> attach(Attachments&&... attachments) KJ_WARN_UNUSED_RESULT;
    229   // Returns an Own<T> which points to the same object but which also ensures that all values
    230   // passed to `attachments` remain alive until after this object is destroyed. Normally
    231   // `attachments` are other Own<?>s pointing to objects that this one depends on.
    232   //
    233   // Note that attachments will eventually be destroyed in the order they are listed. Hence,
    234   // foo.attach(bar, baz) is equivalent to (but more efficient than) foo.attach(bar).attach(baz).
    235 
    236   template <typename U>
    237   Own<U> downcast() {
    238     // Downcast the pointer to Own<U>, destroying the original pointer.  If this pointer does not
    239     // actually point at an instance of U, the results are undefined (throws an exception in debug
    240     // mode if RTTI is enabled, otherwise you're on your own).
    241 
    242     Own<U> result;
    243     if (ptr != nullptr) {
    244       result.ptr = &kj::downcast<U>(*ptr);
    245       result.disposer = disposer;
    246       ptr = nullptr;
    247     }
    248     return result;
    249   }
    250 
    251 #define NULLCHECK KJ_IREQUIRE(ptr != nullptr, "null Own<> dereference")
    252   inline T* operator->() { NULLCHECK; return ptr; }
    253   inline const T* operator->() const { NULLCHECK; return ptr; }
    254   inline _::RefOrVoid<T> operator*() { NULLCHECK; return *ptr; }
    255   inline _::RefOrVoid<const T> operator*() const { NULLCHECK; return *ptr; }
    256 #undef NULLCHECK
    257   inline T* get() { return ptr; }
    258   inline const T* get() const { return ptr; }
    259   inline operator T*() { return ptr; }
    260   inline operator const T*() const { return ptr; }
    261 
    262 private:
    263   const Disposer* disposer;  // Only valid if ptr != nullptr.
    264   T* ptr;
    265 
    266   inline explicit Own(decltype(nullptr)): disposer(nullptr), ptr(nullptr) {}
    267 
    268   inline bool operator==(decltype(nullptr)) { return ptr == nullptr; }
    269   inline bool operator!=(decltype(nullptr)) { return ptr != nullptr; }
    270   // Only called by Maybe<Own<T>>.
    271 
    272   inline void dispose() {
    273     // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
    274     // dispose again.
    275     T* ptrCopy = ptr;
    276     if (ptrCopy != nullptr) {
    277       ptr = nullptr;
    278       disposer->dispose(const_cast<RemoveConst<T>*>(ptrCopy));
    279     }
    280   }
    281 
    282   template <typename U>
    283   static inline T* cast(U* ptr) {
    284     static_assert(_kj_internal_isPolymorphic((T*)nullptr),
    285         "Casting owned pointers requires that the target type is polymorphic.");
    286     return ptr;
    287   }
    288 
    289   template <typename U>
    290   friend class Own;
    291   friend class Maybe<Own<T>>;
    292 };
    293 
    294 template <>
    295 template <typename U>
    296 inline void* Own<void>::cast(U* ptr) {
    297   return _::castToVoid(ptr);
    298 }
    299 
    300 template <>
    301 template <typename U>
    302 inline const void* Own<const void>::cast(U* ptr) {
    303   return _::castToConstVoid(ptr);
    304 }
    305 
    306 namespace _ {  // private
    307 
    308 template <typename T>
    309 class OwnOwn {
    310 public:
    311   inline OwnOwn(Own<T>&& value) noexcept: value(kj::mv(value)) {}
    312 
    313   inline Own<T>& operator*() & { return value; }
    314   inline const Own<T>& operator*() const & { return value; }
    315   inline Own<T>&& operator*() && { return kj::mv(value); }
    316   inline const Own<T>&& operator*() const && { return kj::mv(value); }
    317   inline Own<T>* operator->() { return &value; }
    318   inline const Own<T>* operator->() const { return &value; }
    319   inline operator Own<T>*() { return value ? &value : nullptr; }
    320   inline operator const Own<T>*() const { return value ? &value : nullptr; }
    321 
    322 private:
    323   Own<T> value;
    324 };
    325 
    326 template <typename T>
    327 OwnOwn<T> readMaybe(Maybe<Own<T>>&& maybe) { return OwnOwn<T>(kj::mv(maybe.ptr)); }
    328 template <typename T>
    329 Own<T>* readMaybe(Maybe<Own<T>>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; }
    330 template <typename T>
    331 const Own<T>* readMaybe(const Maybe<Own<T>>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; }
    332 
    333 }  // namespace _ (private)
    334 
    335 template <typename T>
    336 class Maybe<Own<T>> {
    337 public:
    338   inline Maybe(): ptr(nullptr) {}
    339   inline Maybe(Own<T>&& t) noexcept: ptr(kj::mv(t)) {}
    340   inline Maybe(Maybe&& other) noexcept: ptr(kj::mv(other.ptr)) {}
    341 
    342   template <typename U>
    343   inline Maybe(Maybe<Own<U>>&& other): ptr(mv(other.ptr)) {}
    344   template <typename U>
    345   inline Maybe(Own<U>&& other): ptr(mv(other)) {}
    346 
    347   inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {}
    348 
    349   inline Own<T>& emplace(Own<T> value) {
    350     // Assign the Maybe to the given value and return the content. This avoids the need to do a
    351     // KJ_ASSERT_NONNULL() immediately after setting the Maybe just to read it back again.
    352     ptr = kj::mv(value);
    353     return ptr;
    354   }
    355 
    356   inline operator Maybe<T&>() { return ptr.get(); }
    357   inline operator Maybe<const T&>() const { return ptr.get(); }
    358 
    359   inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; }
    360 
    361   inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
    362   inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
    363 
    364   Own<T>& orDefault(Own<T>& defaultValue) {
    365     if (ptr == nullptr) {
    366       return defaultValue;
    367     } else {
    368       return ptr;
    369     }
    370   }
    371   const Own<T>& orDefault(const Own<T>& defaultValue) const {
    372     if (ptr == nullptr) {
    373       return defaultValue;
    374     } else {
    375       return ptr;
    376     }
    377   }
    378 
    379   template <typename Func>
    380   auto map(Func&& f) & -> Maybe<decltype(f(instance<Own<T>&>()))> {
    381     if (ptr == nullptr) {
    382       return nullptr;
    383     } else {
    384       return f(ptr);
    385     }
    386   }
    387 
    388   template <typename Func>
    389   auto map(Func&& f) const & -> Maybe<decltype(f(instance<const Own<T>&>()))> {
    390     if (ptr == nullptr) {
    391       return nullptr;
    392     } else {
    393       return f(ptr);
    394     }
    395   }
    396 
    397   template <typename Func>
    398   auto map(Func&& f) && -> Maybe<decltype(f(instance<Own<T>&&>()))> {
    399     if (ptr == nullptr) {
    400       return nullptr;
    401     } else {
    402       return f(kj::mv(ptr));
    403     }
    404   }
    405 
    406   template <typename Func>
    407   auto map(Func&& f) const && -> Maybe<decltype(f(instance<const Own<T>&&>()))> {
    408     if (ptr == nullptr) {
    409       return nullptr;
    410     } else {
    411       return f(kj::mv(ptr));
    412     }
    413   }
    414 
    415 private:
    416   Own<T> ptr;
    417 
    418   template <typename U>
    419   friend class Maybe;
    420   template <typename U>
    421   friend _::OwnOwn<U> _::readMaybe(Maybe<Own<U>>&& maybe);
    422   template <typename U>
    423   friend Own<U>* _::readMaybe(Maybe<Own<U>>& maybe);
    424   template <typename U>
    425   friend const Own<U>* _::readMaybe(const Maybe<Own<U>>& maybe);
    426 };
    427 
    428 namespace _ {  // private
    429 
    430 template <typename T>
    431 class HeapDisposer final: public Disposer {
    432 public:
    433   virtual void disposeImpl(void* pointer) const override { delete reinterpret_cast<T*>(pointer); }
    434 
    435   static const HeapDisposer instance;
    436 };
    437 
    438 #if _MSC_VER && _MSC_VER < 1920 && !defined(__clang__)
    439 template <typename T>
    440 __declspec(selectany) const HeapDisposer<T> HeapDisposer<T>::instance = HeapDisposer<T>();
    441 // On MSVC 2017 we suddenly started seeing a linker error on one specific specialization of
    442 // `HeapDisposer::instance` when seemingly-unrelated code was modified. Explicitly specifying
    443 // `__declspec(selectany)` seems to fix it. But why? Shouldn't template members have `selectany`
    444 // behavior by default? We don't know. It works and we're moving on.
    445 #else
    446 template <typename T>
    447 const HeapDisposer<T> HeapDisposer<T>::instance = HeapDisposer<T>();
    448 #endif
    449 
    450 }  // namespace _ (private)
    451 
    452 template <typename T, typename... Params>
    453 Own<T> heap(Params&&... params) {
    454   // heap<T>(...) allocates a T on the heap, forwarding the parameters to its constructor.  The
    455   // exact heap implementation is unspecified -- for now it is operator new, but you should not
    456   // assume this.  (Since we know the object size at delete time, we could actually implement an
    457   // allocator that is more efficient than operator new.)
    458 
    459   return Own<T>(new T(kj::fwd<Params>(params)...), _::HeapDisposer<T>::instance);
    460 }
    461 
    462 template <typename T>
    463 Own<Decay<T>> heap(T&& orig) {
    464   // Allocate a copy (or move) of the argument on the heap.
    465   //
    466   // The purpose of this overload is to allow you to omit the template parameter as there is only
    467   // one argument and the purpose is to copy it.
    468 
    469   typedef Decay<T> T2;
    470   return Own<T2>(new T2(kj::fwd<T>(orig)), _::HeapDisposer<T2>::instance);
    471 }
    472 
    473 template <typename T, typename... Attachments>
    474 Own<Decay<T>> attachVal(T&& value, Attachments&&... attachments);
    475 // Returns an Own<T> that takes ownership of `value` and `attachments`, and points to `value`.
    476 //
    477 // This is equivalent to heap(value).attach(attachments), but only does one allocation rather than
    478 // two.
    479 
    480 template <typename T, typename... Attachments>
    481 Own<T> attachRef(T& value, Attachments&&... attachments);
    482 // Like attach() but `value` is not moved; the resulting Own<T> points to its existing location.
    483 // This is preferred if `value` is already owned by one of `attachments`.
    484 //
    485 // This is equivalent to Own<T>(&value, kj::NullDisposer::instance).attach(attachments), but
    486 // is easier to write and allocates slightly less memory.
    487 
    488 // =======================================================================================
    489 // SpaceFor<T> -- assists in manual allocation
    490 
    491 template <typename T>
    492 class SpaceFor {
    493   // A class which has the same size and alignment as T but does not call its constructor or
    494   // destructor automatically.  Instead, call construct() to construct a T in the space, which
    495   // returns an Own<T> which will take care of calling T's destructor later.
    496 
    497 public:
    498   inline SpaceFor() {}
    499   inline ~SpaceFor() {}
    500 
    501   template <typename... Params>
    502   Own<T> construct(Params&&... params) {
    503     ctor(value, kj::fwd<Params>(params)...);
    504     return Own<T>(&value, DestructorOnlyDisposer<T>::instance);
    505   }
    506 
    507 private:
    508   union {
    509     T value;
    510   };
    511 };
    512 
    513 // =======================================================================================
    514 // Inline implementation details
    515 
    516 template <typename T>
    517 struct Disposer::Dispose_<T, true> {
    518   static void dispose(T* object, const Disposer& disposer) {
    519     // Note that dynamic_cast<void*> does not require RTTI to be enabled, because the offset to
    520     // the top of the object is in the vtable -- as it obviously needs to be to correctly implement
    521     // operator delete.
    522     disposer.disposeImpl(dynamic_cast<void*>(object));
    523   }
    524 };
    525 template <typename T>
    526 struct Disposer::Dispose_<T, false> {
    527   static void dispose(T* object, const Disposer& disposer) {
    528     disposer.disposeImpl(static_cast<void*>(object));
    529   }
    530 };
    531 
    532 template <typename T>
    533 void Disposer::dispose(T* object) const {
    534   Dispose_<T>::dispose(object, *this);
    535 }
    536 
    537 namespace _ {  // private
    538 
    539 template <typename... T>
    540 struct OwnedBundle;
    541 
    542 template <>
    543 struct OwnedBundle<> {};
    544 
    545 template <typename First, typename... Rest>
    546 struct OwnedBundle<First, Rest...>: public OwnedBundle<Rest...> {
    547   OwnedBundle(First&& first, Rest&&... rest)
    548       : OwnedBundle<Rest...>(kj::fwd<Rest>(rest)...), first(kj::fwd<First>(first)) {}
    549 
    550   // Note that it's intentional that `first` is destroyed before `rest`. This way, doing
    551   // ptr.attach(foo, bar, baz) is equivalent to ptr.attach(foo).attach(bar).attach(baz) in terms
    552   // of destruction order (although the former does fewer allocations).
    553   Decay<First> first;
    554 };
    555 
    556 template <typename... T>
    557 struct DisposableOwnedBundle final: public Disposer, public OwnedBundle<T...> {
    558   DisposableOwnedBundle(T&&... values): OwnedBundle<T...>(kj::fwd<T>(values)...) {}
    559   void disposeImpl(void* pointer) const override { delete this; }
    560 };
    561 
    562 }  // namespace _ (private)
    563 
    564 template <typename T>
    565 template <typename... Attachments>
    566 Own<T> Own<T>::attach(Attachments&&... attachments) {
    567   T* ptrCopy = ptr;
    568 
    569   KJ_IREQUIRE(ptrCopy != nullptr, "cannot attach to null pointer");
    570 
    571   // HACK: If someone accidentally calls .attach() on a null pointer in opt mode, try our best to
    572   //   accomplish reasonable behavior: We turn the pointer non-null but still invalid, so that the
    573   //   disposer will still be called when the pointer goes out of scope.
    574   if (ptrCopy == nullptr) ptrCopy = reinterpret_cast<T*>(1);
    575 
    576   auto bundle = new _::DisposableOwnedBundle<Own<T>, Attachments...>(
    577       kj::mv(*this), kj::fwd<Attachments>(attachments)...);
    578   return Own<T>(ptrCopy, *bundle);
    579 }
    580 
    581 template <typename T, typename... Attachments>
    582 Own<T> attachRef(T& value, Attachments&&... attachments) {
    583   auto bundle = new _::DisposableOwnedBundle<Attachments...>(kj::fwd<Attachments>(attachments)...);
    584   return Own<T>(&value, *bundle);
    585 }
    586 
    587 template <typename T, typename... Attachments>
    588 Own<Decay<T>> attachVal(T&& value, Attachments&&... attachments) {
    589   auto bundle = new _::DisposableOwnedBundle<T, Attachments...>(
    590       kj::fwd<T>(value), kj::fwd<Attachments>(attachments)...);
    591   return Own<Decay<T>>(&bundle->first, *bundle);
    592 }
    593 
    594 }  // namespace kj
    595 
    596 KJ_END_HEADER