You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by GitBox <gi...@apache.org> on 2020/07/23 19:25:24 UTC

[GitHub] [arrow] bkietz commented on a change in pull request #7819: ARROW-9405: [R] Switch to cpp11

bkietz commented on a change in pull request #7819:
URL: https://github.com/apache/arrow/pull/7819#discussion_r459671007



##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }
+
+ private:
+  SEXP from_;
 };
 
 template <typename T>
-struct input_parameter<const std::unique_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::unique_ptr<T>> type;
+class const_reference_input {
+ public:
+  const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}
+
+  using const_reference = const T&;
+  inline operator const_reference() const { return obj_; }

Review comment:
       ```suggestion
     operator const_reference() const { return obj_; }
   ```

##########
File path: r/src/memorypool.cpp
##########
@@ -19,6 +19,11 @@
 #if defined(ARROW_R_WITH_ARROW)
 #include <arrow/memory_pool.h>
 
+template <typename T>
+struct NoDelete {
+  inline void operator()(T* ptr) {}
+};
+

Review comment:
       ```suggestion
   ```
   This can be replaced by a lambda
   ```c++
   std::shared_ptr<arrow::MemoryPool> MemoryPool__default() {
     return std::shared_ptr<arrow::MemoryPool>(arrow::default_memory_pool(),
                                               [](arrow::MemoryPool* not_deleted){});
   }
   ```

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }

Review comment:
       ```suggestion
     operator T() const { return cpp11::as_cpp<T>(from_); }
   ```
   member functions defined in the class body are implicitly inline

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }
+
+ private:
+  SEXP from_;
 };
 
 template <typename T>
-struct input_parameter<const std::unique_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::unique_ptr<T>> type;
+class const_reference_input {
+ public:
+  const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}
+
+  using const_reference = const T&;
+  inline operator const_reference() const { return obj_; }
+
+ private:
+  T obj_;
 };
 
 template <typename T>
-struct input_parameter<const std::vector<std::shared_ptr<T>>&> {
-  typedef typename Rcpp::ConstReferenceVectorSmartPtrInputParameter<std::shared_ptr<T>>
-      type;
+struct input {
+  using type = default_input<T>;
 };
 
-struct wrap_type_shared_ptr_tag {};
-struct wrap_type_unique_ptr_tag {};
-
 template <typename T>
-struct wrap_type_traits<std::shared_ptr<T>> {
-  using wrap_category = wrap_type_shared_ptr_tag;
+struct input<const T&> {
+  using type = const_reference_input<typename std::decay<T>::type>;
 };
 
 template <typename T>
-struct wrap_type_traits<std::unique_ptr<T>> {
-  using wrap_category = wrap_type_unique_ptr_tag;
+struct input<const std::shared_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, std::shared_ptr>;
 };
 
-}  // namespace traits
-
-namespace internal {
+template <typename T>
+using default_unique_ptr = std::unique_ptr<T, std::default_delete<T>>;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag);
+struct input<const std::unique_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, default_unique_ptr>;
+};
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag);
+struct input<const std::vector<std::shared_ptr<T>>&> {
+  using type = ConstRefVectorSmartPtrInput<T, std::shared_ptr>;
+};
 
-}  // namespace internal
-}  // namespace Rcpp
+}  // namespace r
+}  // namespace arrow
 
-#include <Rcpp.h>
+namespace cpp11 {
 
-namespace Rcpp {
-namespace internal {
+template <typename T>
+using is_shared_ptr = typename std::enable_if<
+    std::is_same<std::shared_ptr<typename T::element_type>, T>::value, T>::type;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag) {
-  return Rcpp::XPtr<std::shared_ptr<typename T::element_type>>(
-      new std::shared_ptr<typename T::element_type>(x));
+is_shared_ptr<T> as_cpp(SEXP from) {
+  return arrow::r::ConstRefSmartPtrInput<typename T::element_type, std::shared_ptr>(from);
 }
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag) {
-  return Rcpp::XPtr<std::unique_ptr<typename T::element_type>>(
-      new std::unique_ptr<typename T::element_type>(const_cast<T&>(x).release()));
+inline SEXP as_sexp(const std::shared_ptr<T>& ptr) {

Review comment:
       ```suggestion
   SEXP as_sexp(const std::shared_ptr<T>& ptr) {
   ```
   templates functions are implicitly inline unless fully specialized

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}

Review comment:
       ```suggestion
     explicit default_input(SEXP from) : from_(from) {}
   ```

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }
+
+ private:
+  SEXP from_;
 };
 
 template <typename T>
-struct input_parameter<const std::unique_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::unique_ptr<T>> type;
+class const_reference_input {
+ public:
+  const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}
+
+  using const_reference = const T&;
+  inline operator const_reference() const { return obj_; }
+
+ private:
+  T obj_;
 };
 
 template <typename T>
-struct input_parameter<const std::vector<std::shared_ptr<T>>&> {
-  typedef typename Rcpp::ConstReferenceVectorSmartPtrInputParameter<std::shared_ptr<T>>
-      type;
+struct input {
+  using type = default_input<T>;
 };
 
-struct wrap_type_shared_ptr_tag {};
-struct wrap_type_unique_ptr_tag {};
-
 template <typename T>
-struct wrap_type_traits<std::shared_ptr<T>> {
-  using wrap_category = wrap_type_shared_ptr_tag;
+struct input<const T&> {
+  using type = const_reference_input<typename std::decay<T>::type>;
 };
 
 template <typename T>
-struct wrap_type_traits<std::unique_ptr<T>> {
-  using wrap_category = wrap_type_unique_ptr_tag;
+struct input<const std::shared_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, std::shared_ptr>;
 };
 
-}  // namespace traits
-
-namespace internal {
+template <typename T>
+using default_unique_ptr = std::unique_ptr<T, std::default_delete<T>>;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag);
+struct input<const std::unique_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, default_unique_ptr>;
+};
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag);
+struct input<const std::vector<std::shared_ptr<T>>&> {
+  using type = ConstRefVectorSmartPtrInput<T, std::shared_ptr>;
+};
 
-}  // namespace internal
-}  // namespace Rcpp
+}  // namespace r
+}  // namespace arrow
 
-#include <Rcpp.h>
+namespace cpp11 {
 
-namespace Rcpp {
-namespace internal {
+template <typename T>
+using is_shared_ptr = typename std::enable_if<
+    std::is_same<std::shared_ptr<typename T::element_type>, T>::value, T>::type;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag) {
-  return Rcpp::XPtr<std::shared_ptr<typename T::element_type>>(
-      new std::shared_ptr<typename T::element_type>(x));
+is_shared_ptr<T> as_cpp(SEXP from) {

Review comment:
       ```suggestion
   using enable_if_shared_ptr = typename std::enable_if<
        std::is_same<std::shared_ptr<typename T::element_type>, T>::value, T>::type; 
   
   template <typename T>
   enable_if_shared_ptr<T> as_cpp(SEXP from) {
   ```
   Names `is_*` are conventionally reserved for `bool_constant`s, the prefix `enable_if_` will make it clearer that this is an SFINAE helper

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}

Review comment:
       Or if you need implicit conversion here,
   ```suggestion
     default_input(SEXP from) : from_(from) {}  // NOLINT runtime/explicit
   ```

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }
+
+ private:
+  SEXP from_;
 };
 
 template <typename T>
-struct input_parameter<const std::unique_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::unique_ptr<T>> type;
+class const_reference_input {
+ public:
+  const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}

Review comment:
       ```suggestion
     explicit const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}
   ```

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }
+
+ private:
+  SEXP from_;
 };
 
 template <typename T>
-struct input_parameter<const std::unique_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::unique_ptr<T>> type;
+class const_reference_input {
+ public:
+  const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}
+
+  using const_reference = const T&;
+  inline operator const_reference() const { return obj_; }
+
+ private:
+  T obj_;
 };
 
 template <typename T>
-struct input_parameter<const std::vector<std::shared_ptr<T>>&> {
-  typedef typename Rcpp::ConstReferenceVectorSmartPtrInputParameter<std::shared_ptr<T>>
-      type;
+struct input {
+  using type = default_input<T>;
 };
 
-struct wrap_type_shared_ptr_tag {};
-struct wrap_type_unique_ptr_tag {};
-
 template <typename T>
-struct wrap_type_traits<std::shared_ptr<T>> {
-  using wrap_category = wrap_type_shared_ptr_tag;
+struct input<const T&> {
+  using type = const_reference_input<typename std::decay<T>::type>;
 };
 
 template <typename T>
-struct wrap_type_traits<std::unique_ptr<T>> {
-  using wrap_category = wrap_type_unique_ptr_tag;
+struct input<const std::shared_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, std::shared_ptr>;
 };
 
-}  // namespace traits
-
-namespace internal {
+template <typename T>
+using default_unique_ptr = std::unique_ptr<T, std::default_delete<T>>;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag);
+struct input<const std::unique_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, default_unique_ptr>;
+};
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag);
+struct input<const std::vector<std::shared_ptr<T>>&> {
+  using type = ConstRefVectorSmartPtrInput<T, std::shared_ptr>;
+};
 
-}  // namespace internal
-}  // namespace Rcpp
+}  // namespace r
+}  // namespace arrow
 
-#include <Rcpp.h>
+namespace cpp11 {
 
-namespace Rcpp {
-namespace internal {
+template <typename T>
+using is_shared_ptr = typename std::enable_if<
+    std::is_same<std::shared_ptr<typename T::element_type>, T>::value, T>::type;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag) {
-  return Rcpp::XPtr<std::shared_ptr<typename T::element_type>>(
-      new std::shared_ptr<typename T::element_type>(x));
+is_shared_ptr<T> as_cpp(SEXP from) {
+  return arrow::r::ConstRefSmartPtrInput<typename T::element_type, std::shared_ptr>(from);
 }
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag) {
-  return Rcpp::XPtr<std::unique_ptr<typename T::element_type>>(
-      new std::unique_ptr<typename T::element_type>(const_cast<T&>(x).release()));
+inline SEXP as_sexp(const std::shared_ptr<T>& ptr) {
+  return Rcpp::XPtr<std::shared_ptr<T>>(new std::shared_ptr<T>(ptr));
 }
 
-}  // namespace internal
-
-}  // namespace Rcpp
+template <typename T>
+inline SEXP as_sexp(const std::vector<std::shared_ptr<T>>& vec) {
+  R_xlen_t n = vec.size();
+  SEXP res = PROTECT(Rf_allocVector(VECSXP, n));
+  for (R_xlen_t i = 0; i < n; i++) {
+    SET_VECTOR_ELT(res, i, as_sexp(vec[i]));
+  }
+  UNPROTECT(1);
+  return res;
+}
 
-namespace Rcpp {
-using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
-using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
-using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
-using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
-using CharacterVector_ = StringVector_;
-using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
-using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+template <typename E, typename std::enable_if<std::is_enum<E>::value>::type* = nullptr>
+inline SEXP as_sexp(E e) {

Review comment:
       ```suggestion
   SEXP as_sexp(E e) {
   ```

##########
File path: r/src/arrow_rcpp.h
##########
@@ -67,120 +71,150 @@ struct ns {
 }  // namespace arrow
 
 namespace Rcpp {
-namespace internal {
+using NumericVector_ = Rcpp::Vector<REALSXP, Rcpp::NoProtectStorage>;
+using IntegerVector_ = Rcpp::Vector<INTSXP, Rcpp::NoProtectStorage>;
+using LogicalVector_ = Rcpp::Vector<LGLSXP, Rcpp::NoProtectStorage>;
+using StringVector_ = Rcpp::Vector<STRSXP, Rcpp::NoProtectStorage>;
+using CharacterVector_ = StringVector_;
+using RawVector_ = Rcpp::Vector<RAWSXP, Rcpp::NoProtectStorage>;
+using List_ = Rcpp::Vector<VECSXP, Rcpp::NoProtectStorage>;
+}  // namespace Rcpp
+
+namespace cpp11 {
+
+template <typename E>
+typename std::enable_if<std::is_enum<E>::value, E>::type as_cpp(SEXP from) {
+  return E(cpp11::as_cpp<int>(from));
+}
+
+}  // namespace cpp11
+
+namespace arrow {
+namespace r {
 
 template <typename Pointer>
-Pointer r6_to_smart_pointer(SEXP self) {
+Pointer r6_to_pointer(SEXP self) {
   return reinterpret_cast<Pointer>(
       R_ExternalPtrAddr(Rf_findVarInFrame(self, arrow::r::symbols::xp)));
 }
 
-}  // namespace internal
-
-template <typename T>
-class ConstReferenceSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefSmartPtrInput {
  public:
-  using const_reference = const T&;
+  using const_reference = const SmartPtr<T>&;
 
-  explicit ConstReferenceSmartPtrInputParameter(SEXP self)
-      : ptr(internal::r6_to_smart_pointer<const T*>(self)) {}
+  explicit ConstRefSmartPtrInput(SEXP self)
+      : ptr(r6_to_pointer<const SmartPtr<T>*>(self)) {}
 
   inline operator const_reference() { return *ptr; }
 
  private:
-  const T* ptr;
+  // this class host
+  const SmartPtr<T>* ptr;
 };
 
-template <typename T>
-class ConstReferenceVectorSmartPtrInputParameter {
+template <typename T, template <class> class SmartPtr>
+class ConstRefVectorSmartPtrInput {
  public:
-  using const_reference = const std::vector<T>&;
+  using const_reference = const std::vector<SmartPtr<T>>&;
 
-  explicit ConstReferenceVectorSmartPtrInputParameter(SEXP self) : vec() {
+  explicit ConstRefVectorSmartPtrInput(SEXP self) : vec() {
     R_xlen_t n = XLENGTH(self);
     for (R_xlen_t i = 0; i < n; i++) {
-      vec.push_back(*internal::r6_to_smart_pointer<const T*>(VECTOR_ELT(self, i)));
+      vec.push_back(*r6_to_pointer<const SmartPtr<T>*>(VECTOR_ELT(self, i)));
     }
   }
 
   inline operator const_reference() { return vec; }
 
  private:
-  std::vector<T> vec;
+  std::vector<SmartPtr<T>> vec;
 };
 
-namespace traits {
-
 template <typename T>
-struct input_parameter<const std::shared_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::shared_ptr<T>> type;
+class default_input {
+ public:
+  default_input(SEXP from) : from_(from) {}
+
+  inline operator T() const { return cpp11::as_cpp<T>(from_); }
+
+ private:
+  SEXP from_;
 };
 
 template <typename T>
-struct input_parameter<const std::unique_ptr<T>&> {
-  typedef typename Rcpp::ConstReferenceSmartPtrInputParameter<std::unique_ptr<T>> type;
+class const_reference_input {
+ public:
+  const_reference_input(SEXP from) : obj_(cpp11::as_cpp<T>(from)) {}
+
+  using const_reference = const T&;
+  inline operator const_reference() const { return obj_; }
+
+ private:
+  T obj_;
 };
 
 template <typename T>
-struct input_parameter<const std::vector<std::shared_ptr<T>>&> {
-  typedef typename Rcpp::ConstReferenceVectorSmartPtrInputParameter<std::shared_ptr<T>>
-      type;
+struct input {
+  using type = default_input<T>;
 };
 
-struct wrap_type_shared_ptr_tag {};
-struct wrap_type_unique_ptr_tag {};
-
 template <typename T>
-struct wrap_type_traits<std::shared_ptr<T>> {
-  using wrap_category = wrap_type_shared_ptr_tag;
+struct input<const T&> {
+  using type = const_reference_input<typename std::decay<T>::type>;
 };
 
 template <typename T>
-struct wrap_type_traits<std::unique_ptr<T>> {
-  using wrap_category = wrap_type_unique_ptr_tag;
+struct input<const std::shared_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, std::shared_ptr>;
 };
 
-}  // namespace traits
-
-namespace internal {
+template <typename T>
+using default_unique_ptr = std::unique_ptr<T, std::default_delete<T>>;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag);
+struct input<const std::unique_ptr<T>&> {
+  using type = ConstRefSmartPtrInput<T, default_unique_ptr>;
+};
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag);
+struct input<const std::vector<std::shared_ptr<T>>&> {
+  using type = ConstRefVectorSmartPtrInput<T, std::shared_ptr>;
+};
 
-}  // namespace internal
-}  // namespace Rcpp
+}  // namespace r
+}  // namespace arrow
 
-#include <Rcpp.h>
+namespace cpp11 {
 
-namespace Rcpp {
-namespace internal {
+template <typename T>
+using is_shared_ptr = typename std::enable_if<
+    std::is_same<std::shared_ptr<typename T::element_type>, T>::value, T>::type;
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_shared_ptr_tag) {
-  return Rcpp::XPtr<std::shared_ptr<typename T::element_type>>(
-      new std::shared_ptr<typename T::element_type>(x));
+is_shared_ptr<T> as_cpp(SEXP from) {
+  return arrow::r::ConstRefSmartPtrInput<typename T::element_type, std::shared_ptr>(from);
 }
 
 template <typename T>
-inline SEXP wrap_dispatch(const T& x, Rcpp::traits::wrap_type_unique_ptr_tag) {
-  return Rcpp::XPtr<std::unique_ptr<typename T::element_type>>(
-      new std::unique_ptr<typename T::element_type>(const_cast<T&>(x).release()));
+inline SEXP as_sexp(const std::shared_ptr<T>& ptr) {
+  return Rcpp::XPtr<std::shared_ptr<T>>(new std::shared_ptr<T>(ptr));
 }
 
-}  // namespace internal
-
-}  // namespace Rcpp
+template <typename T>
+inline SEXP as_sexp(const std::vector<std::shared_ptr<T>>& vec) {

Review comment:
       ```suggestion
   SEXP as_sexp(const std::vector<std::shared_ptr<T>>& vec) {
   ```




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org