Member size() fails for Matrix objects #605

Closed
helmingstay opened this Issue Dec 8, 2016 · 7 comments

Projects

None yet

3 participants

@helmingstay
helmingstay commented Dec 8, 2016 edited

Using Debian stretch, g++ 6.2.0-13, R version 3.3.2 (2016-10-31), Rcpp_0.12.8
Tested with NumericMatrix, Integer Matrix, LogicalMatrix

> sourceCpp('size.cpp')
size.cpp: In function ‘void test_mat(Rcpp::NumericMatrix)’:
size.cpp:13:18: error: request for member ‘size’ is ambiguous
     Rcout << obj.size();

size.cpp:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void test_vec(NumericVector obj){
    Rcout << obj.size();
    Rcout << obj.length();
}

// [[Rcpp::export]]
void test_mat(NumericMatrix obj){
    //problem:
    Rcout << obj.size();
    Rcout << obj.length();
}
@eddelbuettel
Member
eddelbuettel commented Dec 8, 2016 edited

Complete error (why oh why did you hide those?) from r-base Docker image using Debian testing, and fresh install of Rcpp 0.12.8 off CRAN:

> sourceCpp("size.cpp")
size.cpp: In functionvoid test_mat(Rcpp::NumericMatrix)’:
size.cpp:13:18: error: request for membersizeis ambiguous
     Rcout << obj.size();
                  ^~~~
In file included from /usr/local/lib/R/site-library/Rcpp/include/RcppCommon.h:165:0,
                 from /usr/local/lib/R/site-library/Rcpp/include/Rcpp.h:27,
                 from size.cpp:1:
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/MatrixBase.h:47:25: note: candidates are: R_xlen_t Rcpp::MatrixBase<RTYPE, na, MATRIX>::size() const [with int RTYPE = 14; bool na = true; MATRIX = Rcpp::Matrix<14>; R_xlen_t = long int]
         inline R_xlen_t size() const { return static_cast<const MATRIX&>(*this).size() ; }
                         ^~~~
In file included from /usr/local/lib/R/site-library/Rcpp/include/Rcpp/Vector.h:52:0,
                 from /usr/local/lib/R/site-library/Rcpp/include/Rcpp.h:40,
                 from size.cpp:1:
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:274:21: note:                 R_xlen_t Rcpp::Vector<RTYPE, StoragePolicy>::size() const [with int RTYPE = 14; StoragePolicy = Rcpp::PreserveStorage; R_xlen_t = long int]
     inline R_xlen_t size() const {
                     ^~~~
make: *** [size.o] Error 1
g++ -I/usr/share/R/include -DNDEBUG    -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/tmp"   -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-3.3.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c size.cpp -o size.o
/usr/lib/R/etc/Makeconf:141: recipe for target 'size.o' failed
Error in sourceCpp("size.cpp") : 
  Error 1 occurred building shared library.
> 

Thoughts? Why did that bite us before? Matrix has always extended Vector. Weird...

@eddelbuettel
Member
eddelbuettel commented Dec 8, 2016 edited

This SO answer suggests leading the compiler to a preferred version of the ambiguous 'diamond pattern' call via a using class::memberfunc; declaration.

Anybody have experience with that? Had not seen the trick...

@eddelbuettel
Member

That worked -- still in the same Docker container of r-base:

root@278c249b2281:/tmp# diff -ru Rcpp.orig/ Rcpp
diff -ru Rcpp.orig/inst/include/Rcpp/vector/Matrix.h Rcpp/inst/include/Rcpp/vector/Matrix.h
--- Rcpp.orig/inst/include/Rcpp/vector/Matrix.h 2016-11-13 21:30:50.000000000 +0000
+++ Rcpp/inst/include/Rcpp/vector/Matrix.h      2016-12-08 04:23:51.258459848 +0000
@@ -29,6 +29,7 @@
     int nrows ;
 
 public:
+    using Vector<RTYPE, StoragePolicy>::size;
     struct r_type : traits::integral_constant<int,RTYPE>{} ;
     struct can_have_na : traits::true_type{} ;
     typedef MatrixRow<RTYPE> Row ;
Only in Rcpp/src: api.o
Only in Rcpp/src: attributes.o
Only in Rcpp/src: barrier.o
Only in Rcpp/src: Date.o
Only in Rcpp/src: Module.o
Only in Rcpp/src: Rcpp_init.o
Only in Rcpp/src: Rcpp.so
root@278c249b2281:/tmp# 

Then:

root@278c249b2281:/tmp# Rscript -e 'library(Rcpp); sourceCpp("size.cpp")'
root@278c249b2281:/tmp# cat size.cpp 
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void test_vec(NumericVector obj){
    Rcout << obj.size();
    Rcout << obj.length();
}

// [[Rcpp::export]]
void test_mat(NumericMatrix obj){
    //problem:
    Rcout << obj.size();
    Rcout << obj.length();
}
root@278c249b2281:/tmp# 

We probably need more of these, but hey, it's a start.

@helmingstay

With the caveat that I'm well out of my depth...
For objects of class *Matrix (which inherit from Vector)

  • The intended behavior of length() and size() is the same?
  • length() works but size() doesn't
  • length() is defined only in Vector.h
  • size() is defined in Vector.h, VectorBase.h, and MatrixBase.h (but not Matrix.h)
@eddelbuettel
Member

I looked at length() and size() recently and thought they were aliases everywhere. Maybe not...

@thirdwing
Member

@helmingstay I think this is exactly the source of this error.

This should be fixed this (maybe other potential problems).

@eddelbuettel
Member

With the caveat that I'm well out of my depth...

We all are :) Welcome to the C++ club.

@thirdwing Agreed. I should go to bed now; if you can find an alternate clean removing one of the redundant / ambiguous re-definitions -- which won't cause a failure elsewhere -- I'd like that. What I added feels ... like a bandaid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment