From bc47b50d45791bf02199f3c039542a11f84a355e Mon Sep 17 00:00:00 2001 From: sbearrows Date: Mon, 7 Jun 2021 13:53:40 -0600 Subject: [PATCH 01/17] init cpp11 faq --- vignettes/cpp11_faq.Rmd | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 vignettes/cpp11_faq.Rmd diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd new file mode 100644 index 00000000..879b0e52 --- /dev/null +++ b/vignettes/cpp11_faq.Rmd @@ -0,0 +1,19 @@ +--- +title: "cpp11 FAQ" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{cpp11 FAQ} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(cpp11) +``` From 1858b7d21ddb655745ed2ec5192eec924e6dd3eb Mon Sep 17 00:00:00 2001 From: sbearrows Date: Mon, 7 Jun 2021 16:55:49 -0600 Subject: [PATCH 02/17] initial faq setup --- vignettes/cpp11_faq.Rmd | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index 879b0e52..5f76ec2e 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -14,6 +14,38 @@ knitr::opts_chunk$set( ) ``` -```{r setup} -library(cpp11) + + + +* What are the underlying types of cpp11 objects? + +vector | element +--- | --- +integers | int +doubles | double +logicals | r_bool +strings | r_string +raws | uint8_t +list | SEXP + +* How do I create a new empty list? +``` +cpp11::writable::list x; +``` + +* How do I retrieve (named) elements from a named vector/list? + +``` +x["foo"] ``` + +* How can I tell whether a vector is named? +``` +x.names() == R_NilValue; +``` + + + + + + From 50431d283cadf8d92297cd3c07011f2a93887d22 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Tue, 8 Jun 2021 13:59:55 -0600 Subject: [PATCH 03/17] adding more faqs --- vignettes/cpp11_faq.Rmd | 52 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index 5f76ec2e..fd17dd7f 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -14,37 +14,51 @@ knitr::opts_chunk$set( ) ``` +Intended to answer common questions about the usage of cpp11 objects - +##FAQ * What are the underlying types of cpp11 objects? -vector | element ---- | --- -integers | int -doubles | double -logicals | r_bool -strings | r_string -raws | uint8_t -list | SEXP + vector | element + --- | --- + integers | int + doubles | double + logicals | r_bool + strings | r_string + raws | uint8_t + list | SEXP * How do I create a new empty list? -``` -cpp11::writable::list x; -``` + + `cpp11::writable::list x;` * How do I retrieve (named) elements from a named vector/list? -``` -x["foo"] -``` + `x["foo"]` * How can I tell whether a vector is named? -``` -x.names() == R_NilValue; -``` - + `x.names() == R_NilValue;` + +* What are the types for C++ iterators? + + * Iterators are internal classes. An example of an iterator for + doubles would be `cpp11::doubles::iterator` + +* How do I return cpp11::writable::logicals() objects? + + * Use brace initialization: + + ``` + cpp11::cpp_function(code = ' + cpp11::writable::logicals fn2() { + return {false}; + }') + fn2() + #> FALSE + ``` + From 6ef787b1000c9515c83d78c3e4ffe794b11e2923 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Wed, 9 Jun 2021 15:07:08 -0600 Subject: [PATCH 04/17] just some edits --- vignettes/cpp11_faq.Rmd | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index fd17dd7f..adcccaf9 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -16,7 +16,7 @@ knitr::opts_chunk$set( Intended to answer common questions about the usage of cpp11 objects -##FAQ +## FAQ * What are the underlying types of cpp11 objects? @@ -52,13 +52,23 @@ Intended to answer common questions about the usage of cpp11 objects ``` cpp11::cpp_function(code = ' - cpp11::writable::logicals fn2() { - return {false}; - }') + cpp11::writable::logicals fn2() { + return {false}; + }') fn2() #> FALSE ``` + * Otherwise this will return a 0 length logical vector: + + ``` + cpp11::cpp_function(code = ' + cpp11::writable::logicals fn() { + return false; + }') + fn() + #> logical(0) + ``` From bc8fee2e7cd54c8c254945b88e9aaf4a8a0b52a5 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Thu, 10 Jun 2021 11:56:41 -0600 Subject: [PATCH 05/17] adding faqs --- vignettes/cpp11_faq.Rmd | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index adcccaf9..aa1ef4d3 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -69,6 +69,12 @@ Intended to answer common questions about the usage of cpp11 objects fn() #> logical(0) ``` + +* Does cpp11 support default arguments? + + * cpp11 does not support default arguments at this time. Instead cpp11 registered functions can be wrapped in an R function for default argument support + + From 95cdcbcddd5a7b55734eae510e2a0b32081095d2 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Thu, 10 Jun 2021 14:32:30 -0600 Subject: [PATCH 06/17] adding faqs --- vignettes/cpp11_faq.Rmd | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index aa1ef4d3..2af9c235 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -74,6 +74,28 @@ Intended to answer common questions about the usage of cpp11 objects * cpp11 does not support default arguments at this time. Instead cpp11 registered functions can be wrapped in an R function for default argument support + ``` + cpp11::cpp_function(code = ' + std::string fn(bool length) { + if(length) { + return ("length"); + } + return ("width"); + }') + + + full_fn <- function(length = FALSE) { + fn(length) + } + full_fn(TRUE) + #> "length" + full_fn() + #> "width" + + ``` + + * Why do I have to + From e336feede857bb9a714619a0489c02dd435388ce Mon Sep 17 00:00:00 2001 From: sbearrows Date: Fri, 11 Jun 2021 14:07:37 -0600 Subject: [PATCH 07/17] more faqs --- vignettes/cpp11_faq.Rmd | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index 2af9c235..efdba412 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -18,6 +18,20 @@ Intended to answer common questions about the usage of cpp11 objects ## FAQ +* How do I modify a vector in place? + + * Using `writable::` will always make a copy, but it has a move constructor, so you can use `cpp11::writable::integers(std::move(x))` and it won't make a copy of the data. + +* How do I add elements to a named list? + +* How do I create a new empty environment? + +* What happens if I try to get a value that doesn't exist? + +* How can I create a `cpp11:raws` from a `std::string`? + +* What are the differences between `cpp11::sexp` and `SEXP`? + * What are the underlying types of cpp11 objects? vector | element @@ -94,8 +108,33 @@ Intended to answer common questions about the usage of cpp11 objects ``` - * Why do I have to + * Why do I have to include `using namespace` in my code as well as `std::` inside of `[[cpp11::register]]` functions? + * Since namespace definitions will not be in the registration file generated by cpp11, types used in function definitions that are decorated with `[[cpp11::register]]` need to be fully qualified. However type names within those functions will work as expected. + + ``` + # This won't work because the return type is not fully qualified + cpp11::cpp_source(code = '#include \n#include + + using namespace std; + + [[cpp11::register]] + string foobar() { + return string("foo") + "-bar"; + } + ') + + # However this will + cpp11::cpp_source(code = '#include \n#include + + using namespace std; + + [[cpp11::register]] + std::string foobar() { + return string("foo") + "-bar"; + } + ') + ``` From ab91a145b6051ab48e9365917f9c8ae1462cd0db Mon Sep 17 00:00:00 2001 From: sbearrows Date: Mon, 14 Jun 2021 13:45:49 -0600 Subject: [PATCH 08/17] ready for review --- vignettes/cpp11_faq.Rmd | 50 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index efdba412..92a0bca3 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -23,22 +23,62 @@ Intended to answer common questions about the usage of cpp11 objects * Using `writable::` will always make a copy, but it has a move constructor, so you can use `cpp11::writable::integers(std::move(x))` and it won't make a copy of the data. * How do I add elements to a named list? + + ``` + cpp11::cpp_source(code = '#include + using namespace cpp11::literals; + [[cpp11::register]] + cpp11::list fn() { + cpp11::writable::list x; + x.push_back({"foo"_nm = 1}); + return x; + }') + fn() + #> $foo + #> [1] 1 + ``` * How do I create a new empty environment? -* What happens if I try to get a value that doesn't exist? + ``` + auto new_env = cpp11::package("base")["new.env"]; + cpp11::environment my_env(new_env()); + ``` + +* How do I assign and retrieve values in an environment? What happens if I try to get a value that doesn't exist? -* How can I create a `cpp11:raws` from a `std::string`? + ``` + my_env["foo"] = 1; + my_env["foo"] == 1; -* What are the differences between `cpp11::sexp` and `SEXP`? + my_env["bar"] == R_UnboundValue; + ``` + +* How can I create a `cpp11:raws` from a `std::string`? + * Push back the contents individually + ``` + cpp11::cpp_source(code = '#include + [[cpp11::register]] + cpp11::raws fn() { + std::string x("hi"); + cpp11::writable::raws out; + for (auto c : x) { + out.push_back(c); + } + return out; + }') + fn() + #> [1] 68 69 + ``` + * What are the underlying types of cpp11 objects? vector | element --- | --- integers | int doubles | double - logicals | r_bool + logical | r_bool strings | r_string raws | uint8_t list | SEXP @@ -84,6 +124,8 @@ Intended to answer common questions about the usage of cpp11 objects #> logical(0) ``` + * This happens because the first case uses the R_xlen_t size constructor and the second uses the std::initializer_list<>() constructor. + * Does cpp11 support default arguments? * cpp11 does not support default arguments at this time. Instead cpp11 registered functions can be wrapped in an R function for default argument support From 337556d4b7d77aba5e9a00d749a4e60631e15641 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Wed, 16 Jun 2021 09:00:21 -0600 Subject: [PATCH 09/17] incorporate Jims edits --- vignettes/cpp11_faq.Rmd | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index 92a0bca3..fd86ada8 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -18,14 +18,11 @@ Intended to answer common questions about the usage of cpp11 objects ## FAQ -* How do I modify a vector in place? - - * Using `writable::` will always make a copy, but it has a move constructor, so you can use `cpp11::writable::integers(std::move(x))` and it won't make a copy of the data. +#### 1. How do I add elements to a named list? -* How do I add elements to a named list? + * - ``` - cpp11::cpp_source(code = '#include + ```{cpp11} using namespace cpp11::literals; [[cpp11::register]] cpp11::list fn() { @@ -38,7 +35,7 @@ Intended to answer common questions about the usage of cpp11 objects #> [1] 1 ``` -* How do I create a new empty environment? +#### 2. How do I create a new empty environment? ``` auto new_env = cpp11::package("base")["new.env"]; @@ -177,7 +174,9 @@ Intended to answer common questions about the usage of cpp11 objects } ') ``` +* How do I modify a vector in place? + * Using `writable::` will always make a copy, but it has a move constructor, so you can use `cpp11::writable::integers(std::move(x))` and it won't make a copy of the data. From a9665c5a9f0eca43abe4262ce4f40224ca3004e7 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Wed, 16 Jun 2021 17:02:49 -0600 Subject: [PATCH 10/17] improving faq format --- vignettes/cpp11_faq.Rmd | 159 ++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 81 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index fd86ada8..67144ebd 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -20,56 +20,52 @@ Intended to answer common questions about the usage of cpp11 objects #### 1. How do I add elements to a named list? - * + * Use push_back() with named literals to add elements to a named list - ```{cpp11} - using namespace cpp11::literals; - [[cpp11::register]] - cpp11::list fn() { - cpp11::writable::list x; - x.push_back({"foo"_nm = 1}); - return x; - }') - fn() - #> $foo - #> [1] 1 - ``` +```{cpp11} +#include +[[cpp11::register]] +cpp11::list fn() { + cpp11::writable::list x; + x.push_back({"foo"_nm = 1}); + return x; +} +``` #### 2. How do I create a new empty environment? - ``` +```{cpp11} auto new_env = cpp11::package("base")["new.env"]; cpp11::environment my_env(new_env()); - ``` +``` -* How do I assign and retrieve values in an environment? What happens if I try to get a value that doesn't exist? +#### 3. How do I assign and retrieve values in an environment? What happens if I try to get a value that doesn't exist? - ``` +```{cpp11} my_env["foo"] = 1; my_env["foo"] == 1; my_env["bar"] == R_UnboundValue; - ``` +``` -* How can I create a `cpp11:raws` from a `std::string`? +#### 4. How can I create a `cpp11:raws` from a `std::string`? * Push back the contents individually - ``` - cpp11::cpp_source(code = '#include - [[cpp11::register]] - cpp11::raws fn() { - std::string x("hi"); - cpp11::writable::raws out; - for (auto c : x) { - out.push_back(c); - } - return out; - }') - fn() - #> [1] 68 69 - ``` -* What are the underlying types of cpp11 objects? +```{cpp11} + #include + [[cpp11::register]] + cpp11::raws fn() { + std::string x("hi"); + cpp11::writable::raws out; + for (auto c : x) { + out.push_back(c); + } + return out; + } +``` + +#### 5. What are the underlying types of cpp11 objects? vector | element --- | --- @@ -80,78 +76,78 @@ Intended to answer common questions about the usage of cpp11 objects raws | uint8_t list | SEXP -* How do I create a new empty list? +#### 6. How do I create a new empty list? - `cpp11::writable::list x;` +```{cpp11} +cpp11::writable::list x; +``` -* How do I retrieve (named) elements from a named vector/list? +#### 7. How do I retrieve (named) elements from a named vector/list? - `x["foo"]` +```{cpp11} +x["foo"] +``` -* How can I tell whether a vector is named? +#### 8. How can I tell whether a vector is named? - `x.names() == R_NilValue;` +```{cpp11} +x.names() == R_NilValue; +``` -* What are the types for C++ iterators? +#### 9. What are the types for C++ iterators? * Iterators are internal classes. An example of an iterator for doubles would be `cpp11::doubles::iterator` -* How do I return cpp11::writable::logicals() objects? +#### 10. How do I return cpp11::writable::logicals() objects? * Use brace initialization: - ``` - cpp11::cpp_function(code = ' - cpp11::writable::logicals fn2() { - return {false}; - }') - fn2() - #> FALSE - ``` +```{cpp11} +cpp11::writable::logicals fn2() { + return {false}; +} +``` * Otherwise this will return a 0 length logical vector: - ``` - cpp11::cpp_function(code = ' - cpp11::writable::logicals fn() { - return false; - }') - fn() - #> logical(0) - ``` +```{cpp11} +cpp11::writable::logicals fn() { + return false; +} +``` * This happens because the first case uses the R_xlen_t size constructor and the second uses the std::initializer_list<>() constructor. -* Does cpp11 support default arguments? +#### 11. Does cpp11 support default arguments? * cpp11 does not support default arguments at this time. Instead cpp11 registered functions can be wrapped in an R function for default argument support - ``` - cpp11::cpp_function(code = ' - std::string fn(bool length) { - if(length) { - return ("length"); - } - return ("width"); - }') - - - full_fn <- function(length = FALSE) { - fn(length) +```{cpp11} +std::string fn(bool length) { + if(length) { + return ("length"); } - full_fn(TRUE) - #> "length" - full_fn() - #> "width" + return ("width"); +} +``` - ``` +```{r} +full_fn <- function(length = FALSE) { + fn(length) +} +full_fn(TRUE) +#> "length" +full_fn() +#> "width" +``` - * Why do I have to include `using namespace` in my code as well as `std::` inside of `[[cpp11::register]]` functions? +#### 12. Why do I have to include `using namespace` in my code as well as `std::` inside of `[[cpp11::register]]` functions? - * Since namespace definitions will not be in the registration file generated by cpp11, types used in function definitions that are decorated with `[[cpp11::register]]` need to be fully qualified. However type names within those functions will work as expected. + + * Since namespace definitions will not be in the registration file generated by cpp11, types used in function definitions that are decorated with `[[cpp11::register]]` need to be fully qualified. However type names within those functions will work as expected. - ``` +```{cpp11} # This won't work because the return type is not fully qualified cpp11::cpp_source(code = '#include \n#include @@ -173,8 +169,9 @@ Intended to answer common questions about the usage of cpp11 objects return string("foo") + "-bar"; } ') - ``` -* How do I modify a vector in place? +``` + +#### 13. How do I modify a vector in place? * Using `writable::` will always make a copy, but it has a move constructor, so you can use `cpp11::writable::integers(std::move(x))` and it won't make a copy of the data. From 7adb88c680bc82ffa6f338f7a385614dcbbe1b22 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Tue, 22 Jun 2021 10:06:59 -0600 Subject: [PATCH 11/17] using cpp11 knitr engines --- vignettes/cpp11_faq.Rmd | 82 +++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index 67144ebd..e4a4fbb4 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -24,6 +24,10 @@ Intended to answer common questions about the usage of cpp11 objects ```{cpp11} #include + +using namespace cpp11; + + [[cpp11::register]] cpp11::list fn() { cpp11::writable::list x; @@ -35,17 +39,41 @@ cpp11::list fn() { #### 2. How do I create a new empty environment? ```{cpp11} +#include + +using namespace cpp11; + +[[cpp11::register]] +cpp11::environment get_environment() { auto new_env = cpp11::package("base")["new.env"]; cpp11::environment my_env(new_env()); + return my_env; +} + ``` #### 3. How do I assign and retrieve values in an environment? What happens if I try to get a value that doesn't exist? ```{cpp11} - my_env["foo"] = 1; - my_env["foo"] == 1; +#include + +using namespace cpp11; +[[cpp11::register]] +cpp11::r_bool is_foo(){ + auto new_env = cpp11::package("base")["new.env"]; + cpp11::environment my_env(new_env()); + + my_env["foo"] = 5; + cpp11::logicals fofo = (as_cpp(my_env["foo"]) == 1); + + if (my_env["bar"] == R_UnboundValue) { + std::printf(fofo); + return (my_env["bar"] == R_UnboundValue); + } + + +} - my_env["bar"] == R_UnboundValue; ``` #### 4. How can I create a `cpp11:raws` from a `std::string`? @@ -53,9 +81,13 @@ cpp11::list fn() { * Push back the contents individually ```{cpp11} - #include - [[cpp11::register]] - cpp11::raws fn() { +#include + + + +using namespace cpp11; +[[cpp11::register]] +cpp11::raws push() { std::string x("hi"); cpp11::writable::raws out; for (auto c : x) { @@ -124,6 +156,8 @@ cpp11::writable::logicals fn() { * cpp11 does not support default arguments at this time. Instead cpp11 registered functions can be wrapped in an R function for default argument support ```{cpp11} +#include +[[cpp11::register]] std::string fn(bool length) { if(length) { return ("length"); @@ -147,28 +181,30 @@ full_fn() * Since namespace definitions will not be in the registration file generated by cpp11, types used in function definitions that are decorated with `[[cpp11::register]]` need to be fully qualified. However type names within those functions will work as expected. -```{cpp11} - # This won't work because the return type is not fully qualified - cpp11::cpp_source(code = '#include \n#include +The following won't compile +```{cpp11, eval = FALSE} +#include +#include - using namespace std; +using namespace std; - [[cpp11::register]] - string foobar() { - return string("foo") + "-bar"; - } - ') +[[cpp11::register]] +string foobar() { + return string("foo") + "-bar"; +} +``` - # However this will - cpp11::cpp_source(code = '#include \n#include - using namespace std; +But this will compile and work as expected +```{cpp11} +#include +#include - [[cpp11::register]] - std::string foobar() { - return string("foo") + "-bar"; - } - ') +using namespace std; +[[cpp11::register]] +std::string foobar() { + return string("foo") + "-bar"; +} ``` #### 13. How do I modify a vector in place? From f8e9ce16094d80e4a5f5ee4d80dc1e58765dfce9 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Tue, 22 Jun 2021 11:33:45 -0600 Subject: [PATCH 12/17] adding cpp11 knitr engine --- vignettes/cpp11_faq.Rmd | 74 ++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index e4a4fbb4..b5d18b80 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -12,6 +12,7 @@ knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) +library(cpp11) ``` Intended to answer common questions about the usage of cpp11 objects @@ -38,6 +39,8 @@ cpp11::list fn() { #### 2. How do I create a new empty environment? + * Use the C++ `auto` keyword with R's `new.env` to return a new empty environment. This should then be passed to `cpp11::environment` before use + ```{cpp11} #include @@ -54,26 +57,40 @@ cpp11::environment get_environment() { #### 3. How do I assign and retrieve values in an environment? What happens if I try to get a value that doesn't exist? + * To assign and retrieve values in an environment use brackets to access values in your environment by name. + * To check if a named value exists use `my_env["bar"] == R_UnboundValue` which returns `TRUE` if the value is unassigned and NULL. + ```{cpp11} #include using namespace cpp11; [[cpp11::register]] -cpp11::r_bool is_foo(){ +cpp11::r_bool foo_exists(){ auto new_env = cpp11::package("base")["new.env"]; cpp11::environment my_env(new_env()); my_env["foo"] = 5; - cpp11::logicals fofo = (as_cpp(my_env["foo"]) == 1); + cpp11::r_bool fofo = (as_cpp(my_env["foo"]) == 5); - if (my_env["bar"] == R_UnboundValue) { - std::printf(fofo); - return (my_env["bar"] == R_UnboundValue); - } + return (fofo); +} +``` + +```{cpp11} +#include + +using namespace cpp11; +[[cpp11::register]] +cpp11::r_bool bar_exists(){ + auto new_env = cpp11::package("base")["new.env"]; + cpp11::environment my_env(new_env()); + + cpp11::r_bool barbar = (my_env["bar"] == R_UnboundValue); + + return (!barbar); } - ``` #### 4. How can I create a `cpp11:raws` from a `std::string`? @@ -83,48 +100,43 @@ cpp11::r_bool is_foo(){ ```{cpp11} #include - - using namespace cpp11; [[cpp11::register]] cpp11::raws push() { + std::string x("hi"); cpp11::writable::raws out; + for (auto c : x) { out.push_back(c); } + return out; } ``` #### 5. What are the underlying types of cpp11 objects? - vector | element - --- | --- - integers | int - doubles | double - logical | r_bool - strings | r_string - raws | uint8_t - list | SEXP + | vector | element + | --- | --- + | integers | int + | doubles | double + | logical | r_bool + | strings | r_string + | raws | uint8_t + | list | SEXP #### 6. How do I create a new empty list? -```{cpp11} -cpp11::writable::list x; -``` +`cpp11::writable::list x;` #### 7. How do I retrieve (named) elements from a named vector/list? -```{cpp11} -x["foo"] -``` +`x["foo"]` #### 8. How can I tell whether a vector is named? -```{cpp11} -x.names() == R_NilValue; -``` + TODO #### 9. What are the types for C++ iterators? @@ -136,6 +148,10 @@ x.names() == R_NilValue; * Use brace initialization: ```{cpp11} +#include + +using namespace cpp11; +[[cpp11::register]] cpp11::writable::logicals fn2() { return {false}; } @@ -144,6 +160,10 @@ cpp11::writable::logicals fn2() { * Otherwise this will return a 0 length logical vector: ```{cpp11} +#include + +using namespace cpp11; +[[cpp11::register]] cpp11::writable::logicals fn() { return false; } @@ -153,7 +173,7 @@ cpp11::writable::logicals fn() { #### 11. Does cpp11 support default arguments? - * cpp11 does not support default arguments at this time. Instead cpp11 registered functions can be wrapped in an R function for default argument support + * cpp11 does not support default arguments. Instead cpp11 registered functions can be wrapped in an R function for default argument support ```{cpp11} #include From 821d9ecd1a0823c7e61614e54ca7a106304047b3 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Tue, 22 Jun 2021 12:12:09 -0600 Subject: [PATCH 13/17] change false to FALSE --- vignettes/cpp11_faq.Rmd | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index b5d18b80..94af11df 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -30,7 +30,7 @@ using namespace cpp11; [[cpp11::register]] -cpp11::list fn() { +cpp11::list foo_push() { cpp11::writable::list x; x.push_back({"foo"_nm = 1}); return x; @@ -153,7 +153,7 @@ cpp11::raws push() { using namespace cpp11; [[cpp11::register]] cpp11::writable::logicals fn2() { - return {false}; + return {FALSE}; } ``` @@ -165,7 +165,7 @@ cpp11::writable::logicals fn2() { using namespace cpp11; [[cpp11::register]] cpp11::writable::logicals fn() { - return false; + return FALSE; } ``` @@ -178,7 +178,7 @@ cpp11::writable::logicals fn() { ```{cpp11} #include [[cpp11::register]] -std::string fn(bool length) { +std::string dims(bool length) { if(length) { return ("length"); } @@ -187,12 +187,12 @@ std::string fn(bool length) { ``` ```{r} -full_fn <- function(length = FALSE) { - fn(length) +full_dims <- function(length = FALSE) { + dims(length) } -full_fn(TRUE) +full_dims(TRUE) #> "length" -full_fn() +full_dims() #> "width" ``` From 2ea819c4ec4962b428504cfc3e7701523718ca9d Mon Sep 17 00:00:00 2001 From: sbearrows Date: Wed, 23 Jun 2021 10:00:18 -0600 Subject: [PATCH 14/17] added empty method for vecs and updated NEWS --- NEWS.md | 1 + cpp11test/src/test-list.cpp | 11 +++++++++++ inst/include/cpp11/r_vector.hpp | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/NEWS.md b/NEWS.md index 17a55d2d..81fe71b8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,7 @@ # cpp11 0.2.7 +* Added empty() and named() methods for r_vector classes, returning true if empty/named (@sbearrows, #182, #186) * Outputting more informative error message when cpp11 decorators are incorrectly formatted (@sbearrows, #127) * Fix spurious diffs from `tools::package_native_routine_registration_skeleton()` by temporarily using C collation (@sbearrows, #171) * Fix a transient memory leak for functions that return values from `cpp11::unwind_protect()` and `cpp11::safe` (#154) diff --git a/cpp11test/src/test-list.cpp b/cpp11test/src/test-list.cpp index d856e8b8..98fdf1cc 100644 --- a/cpp11test/src/test-list.cpp +++ b/cpp11test/src/test-list.cpp @@ -126,4 +126,15 @@ context("list-C++") { expect_true(first[0] == 1); expect_true(first[1] == 2); } + + test_that("empty() works") { + cpp11::writable::list x; + + expect_true(x.empty()); + + cpp11::writable::list y(1); + + expect_false(y.empty()); + } + } diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 3d9afdd9..3886a745 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -112,6 +112,8 @@ class r_vector { operator sexp() const; + bool empty() const; + /// Provide access to the underlying data, mainly for interface /// compatibility with std::vector SEXP data() const; @@ -394,6 +396,12 @@ inline r_vector::operator sexp() const { return data_; } +template +inline bool r_vector::empty() const { + return (!(this->size() > 0)); +} + + /// Provide access to the underlying data, mainly for interface /// compatibility with std::vector template From 57beaacc19f75ed2fb570003cc69ed1f518f64f0 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Wed, 23 Jun 2021 10:15:52 -0600 Subject: [PATCH 15/17] didnt mean to make changes --- NEWS.md | 1 - cpp11test/src/test-list.cpp | 11 ----------- inst/include/cpp11/r_vector.hpp | 7 ------- 3 files changed, 19 deletions(-) diff --git a/NEWS.md b/NEWS.md index 81fe71b8..17a55d2d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,7 +5,6 @@ # cpp11 0.2.7 -* Added empty() and named() methods for r_vector classes, returning true if empty/named (@sbearrows, #182, #186) * Outputting more informative error message when cpp11 decorators are incorrectly formatted (@sbearrows, #127) * Fix spurious diffs from `tools::package_native_routine_registration_skeleton()` by temporarily using C collation (@sbearrows, #171) * Fix a transient memory leak for functions that return values from `cpp11::unwind_protect()` and `cpp11::safe` (#154) diff --git a/cpp11test/src/test-list.cpp b/cpp11test/src/test-list.cpp index 98fdf1cc..d856e8b8 100644 --- a/cpp11test/src/test-list.cpp +++ b/cpp11test/src/test-list.cpp @@ -126,15 +126,4 @@ context("list-C++") { expect_true(first[0] == 1); expect_true(first[1] == 2); } - - test_that("empty() works") { - cpp11::writable::list x; - - expect_true(x.empty()); - - cpp11::writable::list y(1); - - expect_false(y.empty()); - } - } diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 3886a745..1bcaafb7 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -112,8 +112,6 @@ class r_vector { operator sexp() const; - bool empty() const; - /// Provide access to the underlying data, mainly for interface /// compatibility with std::vector SEXP data() const; @@ -396,11 +394,6 @@ inline r_vector::operator sexp() const { return data_; } -template -inline bool r_vector::empty() const { - return (!(this->size() > 0)); -} - /// Provide access to the underlying data, mainly for interface /// compatibility with std::vector From 63de2cf0cf31d95271ab1a9b7e3aac761a631ac8 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Thu, 1 Jul 2021 10:21:15 -0600 Subject: [PATCH 16/17] add named() method to faq --- vignettes/cpp11_faq.Rmd | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index 94af11df..d04ab0f8 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -136,7 +136,20 @@ cpp11::raws push() { #### 8. How can I tell whether a vector is named? - TODO + * Use the `named()` method for vector classes + +```{cpp11} +#include + +using namespace cpp11; +[[cpp11::register]] +cpp11::r_bool is_named() { + cpp11::writable::list x; + x.push_back({writable::integers ({1})}); + #returns false + return(x.named()); + } +``` #### 9. What are the types for C++ iterators? From b25a42c2c31f9eec3335cea3ff2f988f3ec49ae4 Mon Sep 17 00:00:00 2001 From: sbearrows Date: Thu, 1 Jul 2021 11:20:29 -0600 Subject: [PATCH 17/17] update faq based on changes to false --- inst/include/cpp11/r_vector.hpp | 1 - man/cpp11-package.Rd | 1 + vignettes/cpp11_faq.Rmd | 11 +++++------ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 5db8109e..4b8b8a29 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -406,7 +406,6 @@ inline r_vector::operator sexp() const { return data_; } - /// Provide access to the underlying data, mainly for interface /// compatibility with std::vector template diff --git a/man/cpp11-package.Rd b/man/cpp11-package.Rd index d7931614..4a4f147d 100644 --- a/man/cpp11-package.Rd +++ b/man/cpp11-package.Rd @@ -15,6 +15,7 @@ Provides a header only, C++11 interface to R's C \seealso{ Useful links: \itemize{ + \item \url{https://cpp11.r-lib.org} \item \url{https://github.com/r-lib/cpp11} \item Report bugs at \url{https://github.com/r-lib/cpp11/issues} } diff --git a/vignettes/cpp11_faq.Rmd b/vignettes/cpp11_faq.Rmd index d04ab0f8..088de12b 100644 --- a/vignettes/cpp11_faq.Rmd +++ b/vignettes/cpp11_faq.Rmd @@ -144,10 +144,9 @@ cpp11::raws push() { using namespace cpp11; [[cpp11::register]] cpp11::r_bool is_named() { - cpp11::writable::list x; - x.push_back({writable::integers ({1})}); - #returns false - return(x.named()); + cpp11::writable::list s; + s.push_back({writable::integers ({1})}); + return(s.named()); } ``` @@ -170,9 +169,9 @@ cpp11::writable::logicals fn2() { } ``` - * Otherwise this will return a 0 length logical vector: + * Otherwise this will fail to compile: -```{cpp11} +```{cpp11, eval = FALSE} #include using namespace cpp11;