Kelvin Grove
Kelvin Grove

Reputation: 43

How to make a cpp (Rcpp) function that triggers "useful" error messages if the input types are wrong?

Consider this cpp function

// [[Rcpp::export]]
int timesTwo(int x) {
  return x * 2;
}

If I input an object of wrong type in this function (e.g. "character"), apparently, it will not work and show this error message Error: Not compatible with requested type: [type=character; target=integer].

However, I want to make it a bit more informative, for example

Error in timesTwo(int x)
Error: Not compatible with requested type: [type=character; target=integer].

or

Error in the parameter x of timesTwo(int x)
Error: Not compatible with requested type: [type=character; target=integer].

I want to know how I can do it in cpp?

Upvotes: 4

Views: 130

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 174468

There are two obvious ways to handle this. The first is that you invoke your cpp function via a wrapper in R that does your type checking in advance. For example:

Rcpp::cppFunction('
  int times_two_cpp(int x) {
    return x * 2;
  }')

timesTwo <- function(x) {
  if(!is.integer(x)) stop("'x' should be an integer, not ", typeof(x))
  times_two_cpp(x)
}

Testing, we have:

timesTwo(5L)
#> [1] 10

timesTwo('hello')
#> Error in timesTwo("hello") : 'x' should be an integer, not character

The second option is to allow your C++ function to take any R object, and do the type-checking internally. This requires some knowledge of R internals

Rcpp::cppFunction('
  Rcpp::IntegerVector timestwo(SEXP x) {
    if(TYPEOF(x) != INTSXP) {
     Rcpp::stop("in the parameter x of timesTwo - x is not an integer");
    }
    Rcpp::IntegerVector result(x);
    return result * 2;
   }
')

Resulting in

timestwo(5L)
#> [1] 10

timestwo('hello')
#> Error: in the parameter x of timesTwo - x is not an integer

Upvotes: 4

Related Questions