diff --git a/NEWS.md b/NEWS.md index 9ab60147..86e57c48 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # cpp11 (development version) +* `writable::r_vector` default constructors now return a 0 length vector when converted to `SEXP` (#166) * read-only `r_vector` constructors now disallow implicit construction with named arguments (#237) * read-only `r_vector.attr()` methods now return const objects, so it is a compile time error to try to assign to them (#237) * Allow `cpp11::matrix` to be accessed either row-wise or column-wise (the default) depending on the user's choice (@alyst, #229) diff --git a/cpp11test/src/test-list.cpp b/cpp11test/src/test-list.cpp index 2ee5a9e3..0abf6002 100644 --- a/cpp11test/src/test-list.cpp +++ b/cpp11test/src/test-list.cpp @@ -154,4 +154,12 @@ context("list-C++") { cpp11::strings nms(x.names()); expect_true(x.size() == nms.size()); } + + test_that("We don't return NULL for default constructed vectors") { + cpp11::writable::list x; + SEXP y(x); + + expect_true(Rf_xlength(y) == 0); + expect_true(y != R_NilValue); + } } diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 8d244945..206e7b24 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -900,8 +900,12 @@ inline SEXP truncate(SEXP x, R_xlen_t length, R_xlen_t capacity) { template inline r_vector::operator SEXP() const { + auto* p = const_cast*>(this); + if (data_ == R_NilValue) { + p->resize(0); + return data_; + } if (length_ < capacity_) { - auto* p = const_cast*>(this); p->data_ = truncate(p->data_, length_, capacity_); SEXP nms = names(); auto nms_size = Rf_xlength(nms);