Rcpp 将长度为 0 (NULL) 的向量传递给 cppfunction

Rcpp pass vector of length 0 (NULL) to cppfunction

我有一个 cppFunction,输入向量 ints,例如:

library(Rcpp)
cppFunction('double test2(NumericVector ints) {
            return 42;
            }')

如果传递长度至少为 1 的向量,则输出是正确的:

> test2(1)
[1] 42
> test2(1:10)
[1] 42

对于长度为 0 的输入,我得到:

> test2(c())
Error: not compatible with requested type

有什么方法可以将长度为 0 或更大的向量传递给我的函数吗? IE。我的预期输出是:

> test2_expectedoutput(c())
[1] 42

我知道我可以通过首先检查 R 并调用该函数的不同版本来在 R 中对此进行控制,但我想避免这种情况。我希望有一些简单的解决方案,因为如果我正确理解 NumericVector zero; 的作用,在 cpp 中我也可以有一个长度为 0 的 NumericVector 。我能找到的唯一相关问题是 this on how to return a NULL object from within a Rcpp function to R

c() 调用产生 NULL,它不是 numeric 向量。这会在调用 test2 时产生错误。您可以通过 numeric:

构建长度为 0 的数值向量
#check what `c()` does
str(c())
# NULL

# now we try numeric(0)
test2(numeric(0))
#[1] 42

作为一个建议,我认为CFortranC++函数应该很少被直接调用;最好编写一个包装器来执行一些初步操作,例如类型转换等。类似于以下内容:

test2Wrapp<-function(x) test2(as.numeric(x))
test2Wrapp(c())
#[1] 42
#This has the benefit to not calling the internal routines in cases where conversion isn't possible
test2Wrapp(iris)
#Error: (list) object cannot be coerced to type 'double'

几个月前,我们添加了作为 Nullable<T> 传递的功能,这可能正是您在这里想要的。

这是一个简单的例子:

#include <Rcpp.h>

using namespace Rcpp;

// [[Rcpp::export]]
bool checkNull(Nullable<NumericVector> x) {
  if (x.isNotNull()) {
    // do something
    NumericVector xx(x);
    Rcpp::Rcout << "Sum is " << sum(xx) << std::endl;
    return true;
  } else {
    // do nothing
    Rcpp::Rcout << "Nothing to see" << std::endl;
    return false;
  }
}

/*** R
checkNull(1:3)
checkNull(NULL)
*/

及其输出:

R> sourceCpp("/tmp/null.cpp")

R> checkNull(1:3)
Sum is 6
[1] TRUE

R> checkNull(NULL)
Nothing to see
[1] FALSE
R> 

通过模板化,我们尊重预期的类型,但清楚地区分存在与不存在。