Skip to content

Commit c86ab3f

Browse files
authored
Add missing read only implementation for x.at("name") (#384)
* Add failing tests * Add missing implementation * NEWS bullet
1 parent acca2d2 commit c86ab3f

File tree

5 files changed

+36
-10
lines changed

5 files changed

+36
-10
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# cpp11 (development version)
22

3+
* Added the missing implementation for `x.at("name")` for read only vectors
4+
(#370).
5+
36
* Constructors for writable vectors from `initializer_list<named_arg>` now
47
check that `named_arg` contains a length 1 object of the correct type, and
58
throws either a `cpp11::type_error` or `std::length_error` if that is not the

cpp11test/src/test-doubles.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -495,13 +495,21 @@ context("doubles-C++") {
495495
cpp11::writable::doubles x({"a"_nm = 1., "b"_nm = 2.});
496496
cpp11::doubles y(x);
497497

498-
expect_true(x["a"] == 1);
499-
expect_true(x["b"] == 2);
500-
expect_error(x["c"] == 2);
498+
expect_true(x["a"] == 1.);
499+
expect_true(x["b"] == 2.);
500+
expect_error(x["c"]);
501+
502+
expect_true(x.at("a") == 1.);
503+
expect_true(x.at("b") == 2.);
504+
expect_error(x.at("c"));
505+
506+
expect_true(y["a"] == 1.);
507+
expect_true(y["b"] == 2.);
508+
expect_error(y["c"]);
501509

502-
expect_true(y["a"] == 1);
503-
expect_true(y["b"] == 2);
504-
expect_error(y["c"] == 2);
510+
expect_true(y.at("a") == 1.);
511+
expect_true(y.at("b") == 2.);
512+
expect_error(y.at("c"));
505513
}
506514

507515
test_that("doubles::find") {

cpp11test/src/test-integers.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,26 @@ context("integers-C++") {
250250
}
251251
#endif
252252

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

258258
expect_true(x["a"] == 1);
259259
expect_true(x["b"] == 2);
260-
expect_error(x["c"] == 2);
260+
expect_error(x["c"]);
261+
262+
expect_true(x.at("a") == 1);
263+
expect_true(x.at("b") == 2);
264+
expect_error(x.at("c"));
261265

262266
expect_true(y["a"] == 1);
263267
expect_true(y["b"] == 2);
264-
expect_error(y["c"] == 2);
268+
expect_error(y["c"]);
269+
270+
expect_true(y.at("a") == 1);
271+
expect_true(y.at("b") == 2);
272+
expect_error(y.at("c"));
265273
}
266274

267275
test_that("is_na(integer)") {

cpp11test/src/test-list.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ context("list-C++") {
168168
expect_true(x.size() == nms.size());
169169
}
170170

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

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

184184
expect_true(lst.named());
185185
expect_true(lst["name"] == elt);
186+
expect_true(lst.at("name") == elt);
186187

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

190192
UNPROTECT(1);
191193
}

inst/include/cpp11/r_vector.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,11 @@ inline T r_vector<T>::at(const size_type pos) const {
502502
return at(static_cast<R_xlen_t>(pos));
503503
}
504504

505+
template <typename T>
506+
inline T r_vector<T>::at(const r_string& name) const {
507+
return operator[](name);
508+
}
509+
505510
template <typename T>
506511
inline bool r_vector<T>::contains(const r_string& name) const {
507512
SEXP names = this->names();

0 commit comments

Comments
 (0)