Skip to contents

Read and write

In cpp4r, when you declare a variable, it is read-only by default as in cpp11 (Vaughan, Hester, and Francois 2024). This is different from Rcpp, where variables are read-write by default (Eddelbuettel et al. 2024).

Following from the package created in the previous vignette, try to compile and run the following code by adding it to a new file src/04_square_coordinates.h:

[[cpp4r::register]]
integers square_coordinates_(integers x) {
  integers out = x;
  for (int i = 0; i < x.size(); ++i) {
    out[i] = x[i] * x[i];
  }
  return out;
}

devtools::load_all() and devtools::install() will fail with the following error:

error: lvalue required as left operand of assignment
  out[i] = x[i] * x[i];

This is because the argument x is a read-only object, you need to explicitly declare a writable variable:

[[cpp4r::register]]
integers square_coordinates(integers x) {
  writable::integers out = x;
  for (int i = 0; i < x.size(); ++i) {
    out[i] = x[i] * x[i];
  }
  return out;
}

Alternatively, you can declare the argument as writable:

[[cpp4r::register]]
integers square_coordinates_2(writable::integers x) {
  for (int i = 0; i < x.size(); ++i) {
    x[i] = x[i] * x[i];
  }
  return x;
}

Do not forget to include the new header file in main.cpp:

Document these functions with roxygen and compare their outputs after loading the updated package:

cpp4r::register()
devtools::document()
devtools::load_all()

Compare square_coordinates(1:3), square_coordinates(c(1, 2, 3)), and square_coordinates(c(1L, 2L, 3L)). Why do the outputs differ? Are integers and doubles interchangeable as double and int in C++ for reasonable cases?

References

Eddelbuettel, Dirk, Romain Francois, JJ Allaire, Kevin Ushey, Qiang Kou, Nathan Russell, Inaki Ucar, Douglas Bates, and John Chambers. 2024. Rcpp: Seamless r and c++ Integration. https://CRAN.R-project.org/package=Rcpp.
Vaughan, Davis, Jim Hester, and Roman Francois. 2024. “Get Started with Cpp11.” https://cpp11.r-lib.org/articles/cpp11.html#intro.