包中涉及 std::transform 的 Rcpp 代码的兼容性

Compatibility of Rcpp code involving std::transform in package

我正在完成我一直在做的一个包。所有检查看起来都很好,并且在我的电脑上编译没有问题。 win-builder 包也没有问题。作为进一步检查,我尝试在同事的计算机上从源代码安装,但失败了。问题来自我从 :

获取的 Rcpp 函数
NumericVector vecpow(const NumericVector base, const NumericVector exp) {

  NumericVector out(base.size());

  std::transform(base.begin(), base.end(),
                 exp.begin(), out.begin(), ::pow);
  return out;
}

这对我来说编译和工作正常,但在安装时给我的同事抛出一个错误,涉及

error: no matching function function for call to 'transform'

candidate function template not viable: requires 4 arguments, but 5 were provided.

我可以通过将原始代码中的 ::pow 替换为 pow 来重现错误。我在 Windows 8.1,我的同事在 Mac。同事维护自己的包,涉及大量Rcpp代码,通常编译没有问题。

我认为这可能是编译器问题。原始线程有一些涉及 C++11 的替代代码(线程已经五年了),所以原则上,我可以使用替代方法替换有问题的代码。但是,由于我对此不是很有经验,所以这将是反复试验。我的问题是:弹出此错误是否有一个简单的原因?我如何修改我的代码以确保该软件包对大多数用户来说是可安装和可用的?

错误是因为编译器无法将std::pow函数匹配为二元运算(这可能是因为它至少有两个重载,编译器无法猜测类型float/double) 产生以下注释:

note: candidate template ignored: couldn't infer template argument '_BinaryOperation'

然后它退回到一元 std::transform ,它只有 4 个参数推动第二个音符:

note: candidate function template not viable: requires 4 arguments, but 5 were provided

编译停止,因为它没有找到一个有效的 std::transform 来应用于指定的参数。 从 pow 切换到 powf 会停止此问题,因为编译器不必解析任何重载,但是由于此更改可能会丢失精度:

Rcpp::cppFunction("NumericVector vecpow(const NumericVector base, const NumericVector exp) {
  NumericVector out(base.size());
  std::transform(base.begin(), base.end(),
                 exp.begin(), out.begin(), ::powf);
    
  return out;
}
") -> pow
pow(1:5,5:1)
[1]  1 16 27 16  5

另一种解决方法是使用静态转换,即将 ::pow 替换为 static_cast<double(*)(double, double)>(::pow) 以告诉编译器使用 pow[=22= 的 double 重载]