Stereo Stereo - 2 years ago 82
R Question

Comparing two values in Rcpp without casting to specific type

I seek to compare two generic R values in C++ using Rcpp. How can I compare two values without casting them to specific types in C++?

The code that explains my issue is as follows,

src <- "return wrap(x1 == x2);"

fun <- cxxfunction(signature(x1 = "SEXP", x2 = "SEXP"), src, plugin = "Rcpp")

fun("a", "a")

to_cmp <- "a"

fun(to_cmp, to_cmp)

It now gives
where I want it to yield

Since my goal is to implement a data structure in C++ I would prefer to potential user defined

Possible approach

One approach that I tried is,


src <- '
Language call("\`==\`", x1, x2);

return call.eval();

fun <- cxxfunction(signature(x1 = "SEXP", x2 = "SEXP"), src, plugin = "Rcpp")

fun("a", "a")

to_cmp <- "a"

fun(to_cmp, to_cmp)

However, when I run this I get
Error: could not find function "`==`"

Answer Source

You are on the right track with using the generic SEXP input object tag. To get this to work one needs to use C++ templates in addition to TYPEOF(). The prior enables the correct vector creation in the comparison function to be hooked in with Rcpp sugar while the latter enables the correct check and dispatch to occur.

#include <Rcpp.h>
using namespace Rcpp;

template <int RTYPE>
Rcpp::LogicalVector compare_me(Rcpp::Vector<RTYPE> x, Rcpp::Vector<RTYPE> y) {
    return x == y;

// [[Rcpp::export]]
Rcpp::LogicalVector compare_objects(SEXP x, SEXP y) {

    if (TYPEOF(x) == TYPEOF(y)) {
        switch (TYPEOF(x)) {
            case INTSXP:
                return compare_me<INTSXP>(x, y);
            case REALSXP:
                return compare_me<REALSXP>(x, y);
            case STRSXP:
                return compare_me<STRSXP>(x, y);
                Rcpp::stop("Type not supported");
    } else {
        Rcpp::stop("Objects are of different type");

    // Never used, but necessary to avoid the compiler complaining
    // about a missing return statement
    return Rcpp::LogicalVector(); 


to_cmp <- "a"
compare_objects(to_cmp, to_cmp)


[1] TRUE

Also, the above is for use with Rcpp::sourceCpp(). I would encourage you to switch from using inline to using Rcpp::cppFunction() for function definitions as it allows you to focus on the computation and not the setup.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download