From 7e70085266754af3626772cdb1e9ec37097e90d5 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Tue, 20 Aug 2024 14:31:11 -0400 Subject: [PATCH 1/3] Add failing tests --- cpp11test/src/test-doubles.cpp | 20 ++++++++++++++------ cpp11test/src/test-integers.cpp | 14 +++++++++++--- cpp11test/src/test-list.cpp | 4 +++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/cpp11test/src/test-doubles.cpp b/cpp11test/src/test-doubles.cpp index 1d7d62a8..fe6be0c4 100644 --- a/cpp11test/src/test-doubles.cpp +++ b/cpp11test/src/test-doubles.cpp @@ -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") { diff --git a/cpp11test/src/test-integers.cpp b/cpp11test/src/test-integers.cpp index 1a9b7873..f00a9f22 100644 --- a/cpp11test/src/test-integers.cpp +++ b/cpp11test/src/test-integers.cpp @@ -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)") { diff --git a/cpp11test/src/test-list.cpp b/cpp11test/src/test-list.cpp index 3430af2b..777bc540 100644 --- a/cpp11test/src/test-list.cpp +++ b/cpp11test/src/test-list.cpp @@ -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); @@ -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); } From 8c5966c0b874e66bf1f41aedffd3eba35f27497e Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Tue, 20 Aug 2024 14:32:14 -0400 Subject: [PATCH 2/3] Add missing implementation --- inst/include/cpp11/r_vector.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 3d15e5d1..d548b390 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -502,6 +502,11 @@ inline T r_vector::at(const size_type pos) const { return at(static_cast(pos)); } +template +inline T r_vector::at(const r_string& name) const { + return operator[](name); +} + template inline bool r_vector::contains(const r_string& name) const { SEXP names = this->names(); From b36f32d9e96cbe6ebe1229f4481a6e049fedfff4 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Tue, 20 Aug 2024 14:34:36 -0400 Subject: [PATCH 3/3] NEWS bullet --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 5bc63ce2..8ca9fa23 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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` 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