r-lib / cpp11

cpp11 helps you to interact with R objects using C++ code.
https://cpp11.r-lib.org/
Other
193 stars 46 forks source link

Assigning an attribute to an empty vector in c++ produces an error #315

Open pepijn-devries opened 1 year ago

pepijn-devries commented 1 year ago

Thanks for your work on cpp11!

Please consider the following. In c++ the code below will produce the error: attempt to set an attribute on NULL

// Create an empty vector of raws:
cpp11::writable::raws x;
// Assign an attribute:
x.attr("my_attr") = "test";

This would make sense when x actually is a NULL, since in R the following code will produce the same error:

# Assign a NULL to 'x'
x <- NULL
# Try to set an attribute, which is not possible:
attr(x, "my_attr") <- "test"

However, I would expect the c++ code to behave as the following R code:

# Assign an empty vector of raws to 'x'
x <- raw(0)
# Set an attribute. No problems here
attr(x, "my_attr") <- "test"

which works fine.

My question is: Is this expected behaviour from cpp11? If so what would be the recommended strategy to set an attribute to an empty vector (i.e., a vector of a defined type but length zero) in c++ using cpp11. If this is not expected behaviour, can it be fixed?

My session looks like this:

R version 4.1.1 (2021-08-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale:
[1] LC_COLLATE=Dutch_Netherlands.1252  LC_CTYPE=Dutch_Netherlands.1252    LC_MONETARY=Dutch_Netherlands.1252
[4] LC_NUMERIC=C                       LC_TIME=Dutch_Netherlands.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] cpp11_0.4.2

loaded via a namespace (and not attached):
 [1] compiler_4.1.1  magrittr_2.0.3  cli_3.4.1       tools_4.1.1     fs_1.5.0        glue_1.6.2      rstudioapi_0.13
 [8] vctrs_0.6.2     usethis_2.0.1   lifecycle_1.0.3 rlang_1.1.0     purrr_1.0.1
stephematician commented 1 year ago

I find it useful as is - under the hood it means that cpp11 doesn't make new expressions for R to manage unless (explicitly) asked to. For what it's worth, an empty vector in cpp11 can be initialised with:

cpp11::writable::doubles x(0);
// x <- numeric(0)
pepijn-devries commented 1 year ago

Thank you for the quick response and clarification. However, your code won't compile on my machine, letting me know that call to constructor of writable::doubles (aka as 'r_vector') is ambiguous... I had to explicitly cast the int to R_xlen_t like so:

cpp11::writable::doubles x((R_xlen_t)0);

After this I was indeed able to set an attribute value;

Maybe some attention to the initialisation of vectors could be given in one of the vignettes?

stephematician commented 1 year ago

Ah I forgot that zero can be used to initialise other types and that leads to ambiguity. Definitely something that should be documented.