From 84ee6ace9510872298872f6952f5e6132b353f2f Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Fri, 26 Jun 2026 09:09:43 -0700 Subject: [PATCH 1/2] fix ListOf compile by not relying on get__() in attribute accessors AttributeProxyPolicy is a base class whose CLASS template parameter need not provide get__() (that comes from the storage policy). ListOf inherits AttributeProxyPolicy without a storage policy, so hasAttribute() and attributeNames() failed to compile for it. Use the operator SEXP() conversion every such class provides instead, matching the existing R_getAttribNames() call. Fixes #1483. --- inst/NEWS.Rd | 3 +++ inst/include/Rcpp/proxy/AttributeProxy.h | 4 ++-- inst/tinytest/cpp/ListOf.cpp | 10 ++++++++++ inst/tinytest/test_listof.R | 12 ++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 75b6467fd..18086f373 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -36,6 +36,9 @@ has been fixed (Kevin in \ghpr{1475} fixing \ghit{1474}) \item The \code{Nullable::operatorT()} has been added as a 'opt-out' (Dirk in \ghpr{1477} with coordination in \ghit{1472}) + \item The attribute accessors in \code{AttributeProxyPolicy} no longer + rely on \code{get__()} so that classes such as \code{ListOf} compile + (Kevin in \ghpr{1484} fixing \ghit{1483}) } \item Changes in Rcpp Documentation: \itemize{ diff --git a/inst/include/Rcpp/proxy/AttributeProxy.h b/inst/include/Rcpp/proxy/AttributeProxy.h index f3e31466f..859d67632 100644 --- a/inst/include/Rcpp/proxy/AttributeProxy.h +++ b/inst/include/Rcpp/proxy/AttributeProxy.h @@ -86,7 +86,7 @@ class AttributeProxyPolicy { v.push_back(std::string(CHAR(STRING_ELT(attrs, i)))); } #else - SEXP attrs = ATTRIB( static_cast(*this).get__()); + SEXP attrs = ATTRIB( static_cast(*this) ); while( attrs != R_NilValue ){ v.push_back( std::string(CHAR(PRINTNAME(TAG(attrs)))) ) ; attrs = CDR( attrs ) ; @@ -97,7 +97,7 @@ class AttributeProxyPolicy { bool hasAttribute(const std::string& attr) const { #if R_VERSION >= R_Version(4, 6, 0) - return R_hasAttrib(static_cast(*this).get__(), Rf_install(attr.c_str())); + return R_hasAttrib(static_cast(*this), Rf_install(attr.c_str())); #else return static_cast(*this).attr(attr) != R_NilValue; #endif diff --git a/inst/tinytest/cpp/ListOf.cpp b/inst/tinytest/cpp/ListOf.cpp index 05af92d61..9a5687b02 100644 --- a/inst/tinytest/cpp/ListOf.cpp +++ b/inst/tinytest/cpp/ListOf.cpp @@ -113,3 +113,13 @@ CharacterVector listof_names(ListOf x) { SEXP listof_attr_foo(ListOf x) { return x.attr("foo"); } + +// [[Rcpp::export]] +bool listof_has_attr(ListOf x, std::string name) { + return x.hasAttribute(name); +} + +// [[Rcpp::export]] +std::vector listof_attribute_names(ListOf x) { + return x.attributeNames(); +} diff --git a/inst/tinytest/test_listof.R b/inst/tinytest/test_listof.R index 46ed68c8f..f46cd528d 100644 --- a/inst/tinytest/test_listof.R +++ b/inst/tinytest/test_listof.R @@ -72,3 +72,15 @@ expect_equal(listof_names(l), c("a", "b", "c")) l <- list(a = 1L) attr(l, "foo") <- "bar" expect_equal(listof_attr_foo(l), "bar") + +# test.ListOf.has.attribute <- function() { # GH issue #1483 +l <- list(a = 1L) +attr(l, "foo") <- "bar" +expect_true(listof_has_attr(l, "foo")) +expect_true(listof_has_attr(l, "names")) +expect_false(listof_has_attr(l, "missing")) + +# test.ListOf.attribute.names <- function() { # GH issue #1483 +l <- list(a = 1L) +attr(l, "foo") <- "bar" +expect_true(all(c("names", "foo") %in% listof_attribute_names(l))) From 8fe42cb719a82c2cd6bf38764703dcdab4a0ebfe Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Fri, 26 Jun 2026 10:46:17 -0700 Subject: [PATCH 2/2] add ChangeLog entry --- ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 811a2abde..ecf4913d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2026-06-26 Kevin Ushey + + * inst/include/Rcpp/proxy/AttributeProxy.h: Do not rely on get__() + in attribute accessors so that classes such as ListOf compile + * inst/tinytest/cpp/ListOf.cpp: Added tests + * inst/tinytest/test_listof.R: Idem + 2026-06-18 Dirk Eddelbuettel * vignettes/rmd/Rcpp.bib: Updated references