# cpp11 FAQ

Intended to answer common questions about the usage of cpp11 objects

## FAQ

#### 1. How do I add elements to a named list?

- Use push_back() with named literals to add elements to a named list

    #include <cpp11.hpp>

    using namespace cpp11;

    [[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?

- 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

    #include <cpp11.hpp>

    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?

- 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.

    #include <cpp11.hpp>

    using namespace cpp11;
    [[cpp11::register]]
    cpp11::r_bool foo_exists(){
      auto new_env = cpp11::package("base")["new.env"];
      cpp11::environment my_env(new_env());

      my_env["foo"] = 5;
      cpp11::r_bool fofo = (as_cpp<int>(my_env["foo"]) == 5);

      return (fofo);
    }

    #include <cpp11.hpp>

    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`?

- Push back the contents individually

    #include <cpp11.hpp>

    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

#### 6. How do I create a new empty list?

`cpp11::writable::list x;`

#### 7. How do I retrieve (named) elements from a named vector/list?

`x["foo"]`

#### 8. How can I tell whether a vector is named?

TODO

#### 9. What are the types for C++ iterators?

- Iterators are internal classes. An example of an iterator for doubles would be `cpp11::doubles::iterator`

#### 10. How do I return cpp11::writable::logicals() objects?

- Use brace initialization:

    #include <cpp11.hpp>

    using namespace cpp11;
    [[cpp11::register]]
    cpp11::writable::logicals fn2() {
      return {false};
    }

- Otherwise this will return a 0 length logical vector:

    #include <cpp11.hpp>

    using namespace cpp11;
    [[cpp11::register]]
    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.

#### 11. Does cpp11 support default arguments?

- cpp11 does not support default arguments. Instead cpp11 registered functions can be wrapped in an R function for default argument support

    #include <cpp11.hpp>
    [[cpp11::register]]
    std::string fn(bool length) {
      if(length) {
        return ("length");
      }
      return ("width");
    }

    full_fn <- function(length = FALSE) {
      fn(length)
    }
    full_fn(TRUE)
    #> [1] "length"
    #> "length"
    full_fn()
    #> [1] "width"
    #> "width"

#### 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.

The following won’t compile

    #include <cpp11.hpp>
    #include <string>

    using namespace std;

    [[cpp11::register]]
    string foobar() {
      return string("foo") + "-bar";
    }

But this will compile and work as expected

    #include <cpp11.hpp>
    #include <string>

    using namespace std;
    [[cpp11::register]]
    std::string foobar() {
      return string("foo") + "-bar";
    }

#### 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.