Skip to content

Add missing read only implementation for x.at("name") #384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading