Rcpp需要一个复制构造函数

时间:2018-04-11 22:37:23

标签: c++ c++11 rcpp

我尝试使用Rcpp将一些C ++ 11功能导出到R.其中一些函数使用std::unique_ptr返回结果。这个东西无法复制。下面的MCVE使用std::unique_ptr<std::string>来说明错误。

我在unique_ptr周围创建了一个类,希望能让所有这些成为可能,但无济于事。这是下面的PtrClassOwner。函数createClassWrapper调用原始createClass,将unique_ptr粘贴到PtrClassOwner对象中。

#include <RcppCommon.h>
#include <memory>
#include <string>

// Stuff to wrap:

using PtrClass = std::unique_ptr<std::string>;

PtrClass createClass() { return PtrClass{new std::string("boo")}; }

// ---

class PtrClassOwner {
public:
    PtrClass string;
};

PtrClassOwner createClassWrapper() { return PtrClassOwner{createClass()}; }

RCPP_EXPOSED_WRAP(PtrClassOwner); // Rcpp-extending vignette says RCPP_EXPORT_WRAP, which doesn't exist.
RCPP_EXPOSED_AS(PtrClassOwner);

#include <Rcpp.h>

RCPP_MODULE(Class){
    using namespace Rcpp;

    class_<PtrClassOwner>("PtrClass");

    function("createClass", &createClassWrapper);
}

这是GCC报告的第一个错误(v 5.4,在Linux上):

In file included from /home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/RcppCommon.h:195:0,
                 from rcpp_module.cpp:1:
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap.h: In instantiation of ‘SEXPREC* Rcpp::internal::wrap_dispatch(const T&, Rcpp::traits::wrap_type_module_object_tag) [with T = PtrClassOwner; SEXP = SEXPREC*]’:
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap_end.h:30:38:   required from ‘SEXPREC* Rcpp::wrap(const T&) [with T = PtrClassOwner; SEXP = SEXPREC*]’
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap_end.h:35:20:   required from ‘SEXPREC* Rcpp::module_wrap_dispatch(const T&, Rcpp::traits::normal_wrap_tag) [with T = PtrClassOwner; SEXP = SEXPREC*]’
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap.h:922:40:   required from ‘SEXPREC* Rcpp::module_wrap(const T&) [with T = PtrClassOwner; SEXP = SEXPREC*]’
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/module/Module_generated_CppFunction.h:34:50:   required from ‘SEXPREC* Rcpp::CppFunction0<RESULT_TYPE>::operator()(SEXPREC**) [with RESULT_TYPE = PtrClassOwner; SEXP = SEXPREC*]’
rcpp_module.cpp:26:1:   required from here
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap.h:759:54: error: use of deleted function ‘PtrClassOwner::PtrClassOwner(const PtrClassOwner&)’
             return Rcpp::internal::make_new_object<T>(new T(object));
                                                      ^
rcpp_module.cpp:9:7: note: ‘PtrClassOwner::PtrClassOwner(const PtrClassOwner&)’ is implicitly deleted because the default definition would be ill-formed:
 class PtrClassOwner {
       ^

问题似乎是,要将对象包装到R对象中,需要复制它。 This other question来自遇到类似问题的人,但没有答案。

我创建了一个类似Python的接口,其中Python对象只包含一个指向C ++对象的指针。我觉得很奇怪,Rcpp试图复制对象来包装它。

有没有解决这个问题的方法?是否有可能只包含一个指向R类型对象的指针,并以某种方式仍然正确地管理它的生命周期?我对任何解决方案持开放态度,我没有开始使用Rcpp,它似乎是导出此功能最直接的方法。

1 个答案:

答案 0 :(得分:3)

我到目前为止找到的最简单的解决方案是从std::unique_ptr中提取指针并从中创建std::shared_ptr。 Rcpp将包装它,因为它可以被复制。

#include <Rcpp.h>
#include <memory>
#include <string>

// Stuff to wrap:

using PtrClass = std::unique_ptr<std::string>;

PtrClass createClass() { return PtrClass{new std::string("boo")}; }

// ---

using ShPtrClass = std::shared_ptr<PtrClass::element_type>;

class PtrClassOwner {
public:
    ShPtrClass shPtrClass;
    PtrClassOwner(PtrClass ptr) : shPtrClass(ptr.release()) {}
};

PtrClassOwner createClassWrapper() { return PtrClassOwner{createClass()}; }

std::string getString(PtrClassOwner const& ptr) {
    return *(ptr.shPtrClass);
}

RCPP_EXPOSED_CLASS(PtrClassOwner);

RCPP_MODULE(Class){
    using namespace Rcpp;
    class_<PtrClassOwner>("PtrClass");
    function("createClass", &createClassWrapper, "createClass method");
    function("getString", &getString, "getString method");
}