Skip to content

Commit 84ee6ac

Browse files
committed
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.
1 parent 8d2f8f8 commit 84ee6ac

4 files changed

Lines changed: 27 additions & 2 deletions

File tree

inst/NEWS.Rd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
has been fixed (Kevin in \ghpr{1475} fixing \ghit{1474})
3737
\item The \code{Nullable::operatorT()} has been added as a 'opt-out'
3838
(Dirk in \ghpr{1477} with coordination in \ghit{1472})
39+
\item The attribute accessors in \code{AttributeProxyPolicy} no longer
40+
rely on \code{get__()} so that classes such as \code{ListOf} compile
41+
(Kevin in \ghpr{1484} fixing \ghit{1483})
3942
}
4043
\item Changes in Rcpp Documentation:
4144
\itemize{

inst/include/Rcpp/proxy/AttributeProxy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class AttributeProxyPolicy {
8686
v.push_back(std::string(CHAR(STRING_ELT(attrs, i))));
8787
}
8888
#else
89-
SEXP attrs = ATTRIB( static_cast<const CLASS&>(*this).get__());
89+
SEXP attrs = ATTRIB( static_cast<const CLASS&>(*this) );
9090
while( attrs != R_NilValue ){
9191
v.push_back( std::string(CHAR(PRINTNAME(TAG(attrs)))) ) ;
9292
attrs = CDR( attrs ) ;
@@ -97,7 +97,7 @@ class AttributeProxyPolicy {
9797

9898
bool hasAttribute(const std::string& attr) const {
9999
#if R_VERSION >= R_Version(4, 6, 0)
100-
return R_hasAttrib(static_cast<const CLASS&>(*this).get__(), Rf_install(attr.c_str()));
100+
return R_hasAttrib(static_cast<const CLASS&>(*this), Rf_install(attr.c_str()));
101101
#else
102102
return static_cast<const CLASS&>(*this).attr(attr) != R_NilValue;
103103
#endif

inst/tinytest/cpp/ListOf.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,13 @@ CharacterVector listof_names(ListOf<NumericVector> x) {
113113
SEXP listof_attr_foo(ListOf<NumericVector> x) {
114114
return x.attr("foo");
115115
}
116+
117+
// [[Rcpp::export]]
118+
bool listof_has_attr(ListOf<NumericVector> x, std::string name) {
119+
return x.hasAttribute(name);
120+
}
121+
122+
// [[Rcpp::export]]
123+
std::vector<std::string> listof_attribute_names(ListOf<NumericVector> x) {
124+
return x.attributeNames();
125+
}

inst/tinytest/test_listof.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,15 @@ expect_equal(listof_names(l), c("a", "b", "c"))
7272
l <- list(a = 1L)
7373
attr(l, "foo") <- "bar"
7474
expect_equal(listof_attr_foo(l), "bar")
75+
76+
# test.ListOf.has.attribute <- function() { # GH issue #1483
77+
l <- list(a = 1L)
78+
attr(l, "foo") <- "bar"
79+
expect_true(listof_has_attr(l, "foo"))
80+
expect_true(listof_has_attr(l, "names"))
81+
expect_false(listof_has_attr(l, "missing"))
82+
83+
# test.ListOf.attribute.names <- function() { # GH issue #1483
84+
l <- list(a = 1L)
85+
attr(l, "foo") <- "bar"
86+
expect_true(all(c("names", "foo") %in% listof_attribute_names(l)))

0 commit comments

Comments
 (0)