https://github.com/mpadge/there-is-no-rcpp-const
Note to self: Rcpp passes all its own classes by reference and ignores const
https://github.com/mpadge/there-is-no-rcpp-const
Last synced: 2 months ago
JSON representation
Note to self: Rcpp passes all its own classes by reference and ignores const
- Host: GitHub
- URL: https://github.com/mpadge/there-is-no-rcpp-const
- Owner: mpadge
- Created: 2018-03-19T18:32:51.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2018-03-20T18:18:50.000Z (about 7 years ago)
- Last Synced: 2024-06-11T18:21:38.620Z (12 months ago)
- Language: C++
- Homepage:
- Size: 8.79 KB
- Stars: 5
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
Awesome Lists containing this project
README
# Note to Self: There is no Rcpp const!
```{r load, echo = FALSE, eval = FALSE}
devtools::load_all (".", export_all = FALSE)
devtools::document (".")
````Rcpp` passes all internals objects by reference only, never by value. This repo
demonstrates the implications of this as a clear and simple Note To Self. Note
that this is acknowledged behaviour of `Rcpp`, as clarified by [this `Rcpp`
issue](https://github.com/RcppCore/Rcpp/issues/628), the corresponding [pull
request](https://github.com/RcppCore/Rcpp/pull/661), and the resultant entry in
the [`Rcpp` FAQ, Section
5.1](https://github.com/RcppCore/Rcpp/files/884053/Rcpp-FAQ.pdf).The demo here relies on these `C++` functions
```
// [[Rcpp::export]]
void rcpp_test1(const Rcpp::DataFrame df) {
Rcpp::IntegerVector x = df ["x"];
x = x + 1;
}// [[Rcpp::export]]
void rcpp_test2(const Rcpp::DataFrame df) {
std::vector x = df ["x"];
for (auto i: x)
i++;
}
``````{r, message = FALSE}
devtools::load_all (".", export_all = FALSE)
df <- data.frame (x = 1:5, y = 1:5)
test1 (df)
df
```
Running `test1()` alters the values of `df` because the internal
`Rcpp::IntegerVector` object is constructed strictly by reference only.
Crucially, in doing so, `Rcpp` also **complete ignores the `const` directive**,
as discussed in the FAQ linked above. In contrast, the `rcpp_test2` function
implements an implicit copy-by-value through the typecast to `std::vector`, and
so
```{r}
test2 (df)
df
```
An alternative is `Rcpp::clone()`, as demonstrated in the third function:
```
// [[Rcpp::export]]
void rcpp_test3(const Rcpp::DataFrame df) {
const Rcpp::IntegerVector x = df ["x"];
Rcpp::IntegerVector x2 = Rcpp::clone (x);
x2 = x2 + 1;
}
```
This also leaves the original unmodified:
```{r}
test3 (df)
df
```## moral of the story
The following code is pointless:
```
void rcpp_stuff(const Rcpp:: obj) { ... }
```
because `const` will just be ignored anyway. Never forget that! Easy way is
never to pretend that `const Rcpp::` has any meaning, and just write
this instead:
```
void rcpp_stuff(Rcpp:: obj) { ... }
```