@@ -354,6 +354,8 @@ enum class return_value_policy : uint8_t {
354354    reference_internal
355355};
356356
357+ class  object ;
358+ 
357359NAMESPACE_BEGIN (detail)
358360
359361inline static constexpr  int log2(size_t  n, int  k = 0 ) { return  (n <= 1 ) ? k : log2 (n >> 1 , k + 1 ); }
@@ -373,6 +375,83 @@ constexpr size_t instance_simple_holder_in_ptrs() {
373375    return  size_in_ptrs (sizeof (std::shared_ptr<int >));
374376}
375377
378+ enum  class  HolderTypeId  {
379+     Unknown,
380+     UniquePtr,
381+     SharedPtr,
382+ };
383+ template  <typename  holder_type, typename  SFINAE = void >
384+ struct  get_holder_type_id  {
385+     static  constexpr  HolderTypeId value = HolderTypeId::Unknown;
386+ };
387+ template  <typename  T>
388+ struct  get_holder_type_id <std::shared_ptr<T>, void > {
389+     static  constexpr  HolderTypeId value = HolderTypeId::SharedPtr;
390+ };
391+ template  <typename  T, typename  Deleter>
392+ struct  get_holder_type_id <std::unique_ptr<T, Deleter>, void > {
393+     //  TODO(eric.cousineau): Should this only specialize for `std::default_deleter`?
394+     static  constexpr  HolderTypeId value = HolderTypeId::UniquePtr;
395+ };
396+ 
397+ class  holder_erased  {
398+  public: 
399+     holder_erased () = default ;
400+     holder_erased (const  holder_erased&) = default ;
401+     holder_erased& operator =(const  holder_erased&) = default ;
402+ 
403+     template  <typename  holder_type>
404+     holder_erased (const  holder_type* holder)
405+         : ptr_(const_cast <holder_type*>(holder)),
406+           type_id_ (get_holder_type_id<holder_type>::value),
407+           is_const_(true ) {}
408+ 
409+     template  <typename  holder_type>
410+     holder_erased (holder_type* holder)
411+         : holder_erased(static_cast <const  holder_type*>(holder)) {
412+           is_const_ = false ;
413+     }
414+ 
415+     holder_erased (const  void * ptr, HolderTypeId type_id)
416+         : ptr_(const_cast <void *>(ptr)),
417+           type_id_(type_id),
418+           is_const_(true ) {}
419+ 
420+     holder_erased (void * ptr, HolderTypeId type_id)
421+           : ptr_(ptr),
422+             type_id_(type_id),
423+             is_const_(false ) {}
424+ 
425+     void * ptr () const  { return  ptr_; }
426+     HolderTypeId type_id () const  { return  type_id_; }
427+ 
428+     template  <typename  holder_type>
429+     holder_type& mutable_cast () const  {
430+         if  (is_const_)
431+             throw  std::runtime_error (" Trying to mutate const reference?" 
432+         return  do_cast<holder_type>();
433+     }
434+ 
435+     template  <typename  holder_type>
436+     const  holder_type& cast () const  {
437+         return  do_cast<holder_type>();
438+     }
439+ 
440+     operator  bool () const  { return  ptr_; }
441+  private: 
442+     template  <typename  holder_type>
443+     holder_type& do_cast () const  {
444+         if  (type_id_ != get_holder_type_id<holder_type>::value) {
445+             throw  std::runtime_error (" Mismatch on holder type." 
446+         }
447+         return  *reinterpret_cast <holder_type*>(ptr_);
448+     }
449+ 
450+     void * ptr_{};
451+     HolderTypeId type_id_{HolderTypeId::Unknown};
452+     bool  is_const_{true };
453+ };
454+ 
376455//  Forward declarations
377456struct  type_info ;
378457struct  value_and_holder ;
@@ -423,6 +502,26 @@ struct instance {
423502    // / If true, get_internals().patients has an entry for this object
424503    bool  has_patients : 1 ;
425504
505+     typedef  void  (*release_to_cpp_t )(instance* inst, holder_erased external_holder, object&& obj);
506+     typedef  object  (*reclaim_from_cpp_t )(instance* inst, holder_erased external_holder);
507+ 
508+     struct  type_release_info_t  {
509+       //  Release an instance to C++ for pure C++ instances or Python-derived classes.
510+       release_to_cpp_t  release_to_cpp = nullptr ;
511+ 
512+       //  For classes wrapped in `wrapper<>`. See `move_only_holder_caster` for more info.
513+       //  Pure / direct C++ objects do not need any fancy releasing mechanisms. They are simply
514+       //  unwrapped and passed back.
515+       bool  can_derive_from_wrapper = false ;
516+ 
517+       //  The holder that is contained by this class.
518+       HolderTypeId holder_type_id = HolderTypeId::Unknown;
519+     };
520+     // / If the instance is a Python-derived type that is owned in C++, then this method
521+     // / will permit the instance to be reclaimed back by Python.
522+     //  TODO(eric.cousineau): This may not be necessary. See note in `type_caster_generic::cast`.
523+     reclaim_from_cpp_t  reclaim_from_cpp = nullptr ;
524+ 
426525    // / Initializes all of the above type/values/holders data (but not the instance values themselves)
427526    void  allocate_layout ();
428527
0 commit comments