Skip to content

Commit

Permalink
Add missing read only implementation for x.at("name") (#384)
Browse files Browse the repository at this point in the history
* Add failing tests

* Add missing implementation

* NEWS bullet
  • Loading branch information
DavisVaughan authored Aug 20, 2024
1 parent acca2d2 commit c86ab3f
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 10 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# cpp11 (development version)

* Added the missing implementation for `x.at("name")` for read only vectors
(#370).

* Constructors for writable vectors from `initializer_list<named_arg>` now
check that `named_arg` contains a length 1 object of the correct type, and
throws either a `cpp11::type_error` or `std::length_error` if that is not the
Expand Down
20 changes: 14 additions & 6 deletions cpp11test/src/test-doubles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,13 +495,21 @@ context("doubles-C++") {
cpp11::writable::doubles x({"a"_nm = 1., "b"_nm = 2.});
cpp11::doubles y(x);

expect_true(x["a"] == 1);
expect_true(x["b"] == 2);
expect_error(x["c"] == 2);
expect_true(x["a"] == 1.);
expect_true(x["b"] == 2.);
expect_error(x["c"]);

expect_true(x.at("a") == 1.);
expect_true(x.at("b") == 2.);
expect_error(x.at("c"));

expect_true(y["a"] == 1.);
expect_true(y["b"] == 2.);
expect_error(y["c"]);

expect_true(y["a"] == 1);
expect_true(y["b"] == 2);
expect_error(y["c"] == 2);
expect_true(y.at("a") == 1.);
expect_true(y.at("b") == 2.);
expect_error(y.at("c"));
}

test_that("doubles::find") {
Expand Down
14 changes: 11 additions & 3 deletions cpp11test/src/test-integers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,18 +250,26 @@ context("integers-C++") {
}
#endif

test_that("operator[] with names") {
test_that("operator[] and at with names") {
using namespace cpp11::literals;
cpp11::writable::integers x({"a"_nm = 1, "b"_nm = 2});
cpp11::integers y(x);

expect_true(x["a"] == 1);
expect_true(x["b"] == 2);
expect_error(x["c"] == 2);
expect_error(x["c"]);

expect_true(x.at("a") == 1);
expect_true(x.at("b") == 2);
expect_error(x.at("c"));

expect_true(y["a"] == 1);
expect_true(y["b"] == 2);
expect_error(y["c"] == 2);
expect_error(y["c"]);

expect_true(y.at("a") == 1);
expect_true(y.at("b") == 2);
expect_error(y.at("c"));
}

test_that("is_na(integer)") {
Expand Down
4 changes: 3 additions & 1 deletion cpp11test/src/test-list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ context("list-C++") {
expect_true(x.size() == nms.size());
}

test_that("list::operator[] by name") {
test_that("list::operator[] and at by name") {
SEXP x = PROTECT(Rf_allocVector(VECSXP, 1));

SEXP elt = Rf_allocVector(INTSXP, 1);
Expand All @@ -183,9 +183,11 @@ context("list-C++") {

expect_true(lst.named());
expect_true(lst["name"] == elt);
expect_true(lst.at("name") == elt);

// Lists are the only class where OOB accesses by name return `NULL`
expect_true(lst["oob"] == R_NilValue);
expect_true(lst.at("oob") == R_NilValue);

UNPROTECT(1);
}
Expand Down
5 changes: 5 additions & 0 deletions inst/include/cpp11/r_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,11 @@ inline T r_vector<T>::at(const size_type pos) const {
return at(static_cast<R_xlen_t>(pos));
}

template <typename T>
inline T r_vector<T>::at(const r_string& name) const {
return operator[](name);
}

template <typename T>
inline bool r_vector<T>::contains(const r_string& name) const {
SEXP names = this->names();
Expand Down

0 comments on commit c86ab3f

Please sign in to comment.