Search code examples
rrcpp

R Rcpp std::transform fail


This code worked in 2015 but doesn't now. It reports that there is no matching function for call to transform. Is there some issue with finding the std code now?

#include <Rcpp.h>

using namespace Rcpp;  

// [[Rcpp::export]]
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;
}

/*** R
vecpow(c(0:3), c(4:1))
***/

I found a solution here that involves replacing ::pow with static_cast<double(*)(double, double)>(::pow) At least, it works with the code above.


Solution

  • Yes, the world around us does change every now and then.

    If you consult a C++ reference you see that std::transformed has changed. I am not enough of a language lawyer to see what it dislikes about std::pow now (though I can tell you that you called the wrong (C-level) ::pow) but here are two that work by using a lambda function as in the other older answer.

    Code

    #include <Rcpp.h>
    
    // [[Rcpp::export]]
    std::vector<double> vecpow(const std::vector<double> base,
                               const std::vector<double> exp) {
    
        std::vector<double> out(base.size());
        std::transform(base.begin(), base.end(), exp.begin(), out.begin(),
                       [&](double lhs, double rhs) -> double { 
                                            return std::pow(lhs, rhs); });
        return out;
    }
    
    // [[Rcpp::export]]
    Rcpp::NumericVector vecpow2(Rcpp::NumericVector base, Rcpp::NumericVector exp) {
    
        Rcpp::NumericVector out(base.size());
        std::transform(base.begin(), base.end(), exp.begin(), out.begin(),
                       [&](double lhs, double rhs) -> double {
                                            return std::pow(lhs, rhs); });
        return out;
    }
    
    /*** R
    vecpow(0:3, 4:1)
    vecpow2(0:3, 4:1)
    */
    

    Output

    > Rcpp::sourceCpp("answer.cpp")
    
    > vecpow(0:3, 4:1)
    [1] 0 1 4 3
    
    > vecpow2(0:3, 4:1)
    [1] 0 1 4 3
    >