在Rcpp中通过省略号传递许多论证(...)

时间:2014-07-05 22:06:21

标签: r rcpp

我正在尝试使用...来传递rcpp函数中的参数但它无效。如何正确地做到这一点?

NumericVector function(SEXP xR, ...){
    NumericVector x(xR);
    int lenx = x.size();
    NumericVector ret(lenx);
    for(int i=0; i < lenx; i++){
        if(x[i]<0){
            ret[i] = 0;
        }else if(x[i]>1){
            ret[i] = 1;
        }else{  
            ret[i] = anotherfunction(x[i], ...);
        }       
    }
    return ret; 
}

在当前版本中,我收到此错误: expected primary-expression before '...' token

2 个答案:

答案 0 :(得分:10)

Rcpp11具有DotsNamedDots类的可变数量参数的概念。你会做这样的事情:

#include <Rcpp11>

List force_dots( const Dots& dots ){
    List out(n) ;
    for( int i=0; i<n; i++){
        out[i] = Rcpp_eval( dots.promise(i), dots.environment(i)) ;    
    }
    return out ;
}

// [[export]]  
List dots_example(NumericVector x, Dots dots){
    int n = dots.size() ;
    List args = force_dots(dots) ;
    return args ;
}

/*** R
    dots_example(1:10, "e" )
    # [[1]]
    # [1] "e"
*/

在此文件上使用attributes::sourceCpp时,会得到一个带省略号的R函数:

> dots_example
function(x, ...){
  res <- .Call( "sourceCpp_dots_example" , x, environment())
  res
}

这只能部分回答这个问题,即如何将来自R的可变数量的参数传递给C ++。

当您调用do.call函数时,您还需要类似于R another_function的内容。现在你需要手动完成,直到找到实现有用的do_call

的方法

答案 1 :(得分:5)

您可能会将R语言构造...与您认为也存在于C ++中的内容混淆。虽然由于来自R的接口,C ++确实有varargs Rcpp不支持。我们只有.Call()接口

 SEXP somefunction(SEXP a, SEXP b, SEXP c, ...)

这里...在字面意义上仅用于阐述:你可以有0,1,2,3,...... SEXP个参数。但是那些使用的人必须是完全合格的。简而言之,使用...会导致语法错误。有关详细信息,请参阅Section 5.9 of Writing R Extensions

作为旁注,这就是为什么我们在Rcpp中有宏生成的代码。现在,使用C ++ 11,您还可以在C ++代码中使用可变参数模板(Rcpp11在其内部代码中使用它们很有效),但这当然不会改变R的接口,这仍然是相同的.Call()接口,因此受到同样的限制。变量模板非常好用,可以在你的C ++代码中使用Rcpp或Rcpp11,但它们不会将接口更改为R.你需要一组固定的参数,并且不能依赖变量数。

也就是说,如果你只是传递一个List对象作为你的一个参数,那么你可以随意按位置或名称遍历它并检查内容。这是与你的问题最接近的精神。