Michael Weylandt — written Mar 27, 2018 — source
Rcpp
has an elegant mechanism of exception handling
whereby C++
exceptions are automatically translated to errors in R
. For most
projects, the Rcpp::stop
wrapper (in conjunction with the BEGIN_RCPP
and
END_RCPP
macros automatically inserted by
RcppAttributes
)
is sufficient and easy to use, providing an Rcpp
equivalent of base::stop
.
By default, it captures the call stack and attaches it to the exception
in R
, giving informative error messages:
Error in add1(1:5, 1:3): x and y are not the same length!
This matches the default behavior of base::stop()
which captures the call info.
For complex calling patterns (e.g., creating an argument list and calling the
Rcpp
function with do.call
), the resulting error messages are less helpful:
Error in (function (x, y) : x and y are not the same length!
If the internal error were being generated in R
code, we might choose to use
the call.=FALSE
argument to base::stop
to suppress the unhelpful (function (x, y)
part of the error message, but we don’t (immediately) have a corresponding option
in Rcpp
. In this gallery post, we show how to suppress the call-stack capture
of Rcpp::stop
to give cleaner error messages.
The key functionality was added to Rcpp
by Jim Hester in
Rcpp Pull Request #663.
To generate an R
-level exception without a call stack, we pass an optional
false
flag to Rcpp::exception
. For example,
Error: x and y are not the same length!
This can’t capture the R
level call stack, but it is at least cleaner than
the error message from the previous example.
Note that here, as elsewhere in C++
, we need to handle exceptions using a
try/catch
structure, but we do not add it explicitly because
RcppAttributes
automatically handles this for us.
Similar to Rcpp::stop
, Rcpp
also provides a warning
function to generate
R
level warnings. It has the same call-stack capture behavior as stop
.
For the direct call case:
Warning in add4(1:5, 1:3): x and y are not the same length!
[1] 2 4 6 4 5
For the indirect call case:
Warning in (function (x, y) : x and y are not the same length!
[1] 2 4 6 4 5
If we want to suppress the call stack info in this warning, we have to drop
down to the C
-level R
API. In particular, we use the Rf_warningcall
function,
which takes the call as the first argument. By passing a NULL
, we suppress the call:
Warning: x and y are not the same length!
[1] 2 2 3 4 5
The above methods work, but they are not as clean as their Rcpp::stop
and
Rcpp::warning
counterparts. We can take advantage of C++11
to provide
similar functionality for our call-free versions.
Basing our implementation on the C++11
implementation
of Rcpp::stop
and Rcpp::warning
we can define our own
stopNoCall
and warningNoCall
Warning: x and y are not the same length!
[1] 2 4 6 4 5
Error: x and y are not the same length!
Note that we used C++11
variadic templates here – if we wanted to do something
similar in C++98,
we could use essentially the same pattern, but would need to
implement each case individually.