Search code examples
rstdrcpp

Compatibility of Rcpp code involving std::transform in package


I am in the process of finishing a package I've been working on. All checks look good and it compiles without problems on my computer. win-builder has no problems with the package as well. As further check, I've tried to install from source on the computer of a colleague and it fails. The problem comes from a Rcpp function that I've taken from a StackOverflow thread on vector powers in 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;
}

This compiles and works fine for me, but throws an error for my colleague when installing, involving

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

and

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

I can reproduce the error for instance by replacing ::pow in the original code by pow. I'm on Windows 8.1, my colleague is on Mac. The colleague maintains his own packages involving extensive amounts of Rcpp code and usually has no problems with compiling.

I assume that this might be a compiler problem. The original thread has some alternative code involving C++11 (thread is already five years old), so in principle, I could replace the problematic code using alternatives. However, as I'm not very experienced with this, this would be trial and error. My question is: Is there a simple reason why this error pops up? And how can I modify my code in order to be sure that the package will be installable and usable for most users?


Solution

  • the error is caused because the compiler can't match the std::pow function as binary operation (this may be due to the fact that it has at least two overloads and the compiler can't guess the types float/double) giving rise to the following note :

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

    And then it falls back to the unary std::transform which only has 4 arguments pushing the second note:

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

    Compilation stops as it hasn't found a valid std::transform to apply to the specified arguments. Switching from pow to powf stops this issue as the compiler doesn't have to resolve any overloads, however precision might be lost due to this change :

    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
    

    Another work around would be to use static cast i.e replace ::pow with static_cast<double(*)(double, double)>(::pow) to tell the compiler to use the double overload of pow