返回Rcpp :: Vector <RTYPE>元素的类的模板

Tim*_*Tim 1 c++ rcpp

考虑以下几乎没有做任何事情的类:

class MyNumVec
{
  private:
    const NumericVector& x;
  public:
    MyNumVec(const NumericVector& y) : x(y) {}
    double operator[](int i) const { // here
      return x[i];
    }
    operator NumericVector() const { return x; }
};
Run Code Online (Sandbox Code Playgroud)

我想使它更通用,并使用模板,这样我将只使用任何Vector<RTYPE>代替数字向量,但问题是注释标记的行,因为我必须声明输出类型.我尝试使用autoC++ 11中的类型,但它不起作用(" 'auto' return without trailing return type").如何将其转换为适用Vector于任何类型的模板?

nru*_*ell 6

如果你需要坚持使用C++ 98,通常的习惯是使用整数模板参数来表示不同的SEXPTYPEs.在处理Rcpp::*Vector(或Rcpp::*Matrix)时,您通常只关注其中的5个:

# Integer Value SEXPTYPE  R Vector     Rcpp Vector
#            10   LGLSXP   logical   LogicalVector
#            13   INTSXP   integer   IntegerVector
#            14  REALSXP   numeric   NumericVector
#            15  CPLXSXP   complex   ComplexVector
#            16   STRSXP character CharacterVector
Run Code Online (Sandbox Code Playgroud)

完成此操作后,有一些标准的元编程工具可用于Rcpp::traits命名空间中常见的转换:

  • SEXPTYPE - >POD¹类型: storage_type
    • Rcpp::traits::storage_type<REALSXP>::type - > double
    • Rcpp::traits::storage_type<INTSXP>::type - > int
    • 等等
  • POD¹类型 - > SEXPTYPE:r_sexptype_traits
    • Rcpp::traits::r_sexptype_traits<double>::rtype- > 14(REALSXP)
    • Rcpp::traits::r_sexptype_traits<int>::rtype- > 13(INTSXP)
    • 等等

¹ storage_type<STRSXP>::type产生SEXP(特别是a CHARSXP),虽然在技术上是POD类型,但它与其他简单的矢量类型的不同之处在于它的原子单位是不透明的指针(a SEXP),而不是,例如a const char*或者std::string可能是预期的.


一个无趣的例子,RCPP_RETURN_VECTOR用于简洁:

#include <Rcpp.h>

template <int RTYPE>
class MyNumVec {
public:
    typedef Rcpp::Vector<RTYPE> vec_t;
    typedef typename Rcpp::traits::storage_type<RTYPE>::type storage_t;

private:
    const vec_t& x;

public:
    MyNumVec(const vec_t& y)
        : x(y)
    {}

    storage_t operator[](int i) const
    { return x[i]; }

    operator vec_t() const
    { return x; }
};

template <int RTYPE>
Rcpp::Vector<RTYPE> get_first_elem_impl(const Rcpp::Vector<RTYPE>& vec)
{
    MyNumVec<RTYPE> tmp(vec);
    return Rcpp::Vector<RTYPE>::create(tmp[0]);
}

// [[Rcpp::export]]
Rcpp::RObject get_first_elem(Rcpp::RObject x) {
    RCPP_RETURN_VECTOR(get_first_elem_impl, x);
}
Run Code Online (Sandbox Code Playgroud)
get_first_elem(c(TRUE, TRUE, FALSE, TRUE, FALSE))
# [1] TRUE

get_first_elem(1L:5L)
# [1] 1

get_first_elem(1:5 + 0.5)
# [1] 1.5

get_first_elem(1:5 + 2i)
# [1] 1+2i

get_first_elem(letters[1:5])
# [1] "a"
Run Code Online (Sandbox Code Playgroud)