Dear Rcpp-devel,

Apologies in advance for the laborious problem statement.  I hope your experienced eyes will see a trivial mistake obscured to my nascent ones.

We have a C++ core library providing an API that is wrapped in R (Rcpp) and Python (pybind11).

A new feature implements the addition of a boolean vector (validLib) as an API argument.

When adding this to one of the API functions (Simplex), there is no issue.  Note that Simplex returns a DataFrame class object.

When adding the same code to the API function SMap, which returns a list, there seems to be a compiler error regarding the argument as not allowed. (Error Log below).

sessionInfo is also listed below.

The same error (template argument deduction/substitution failed) is found if I replace std::vector< bool > with Rcpp::LogicalVector.

The code layout:

R API is accessed by R package user, function SMap() in R code interface EDM.R.

SMap (R) calls the Rcpp wrapped function RtoCpp_SMap(), returning a list of R data.frames.

RtoCpp_SMap() is mapped to SMap_rcpp() (cpp code in SMap.cpp) in RcppEDMCommon.cpp.

The function SMap_rcpp() calls the C++ API function SMap().  Note, function (SMap) is overloaded.

In RcppEDMCommon.h a prototype is defined. In RcppEDMCommon.cpp an argument list is defined: Protoype in RcppEDMCommon.h

namespace r = Rcpp;

r::List SMap_rcpp( std::string       pathIn,
                   std::string       dataFile,
                   r::DataFrame      dataList,
                   std::string       pathOut,
                   std::string       predictFile,
                   std::string       lib,
                   std::string       pred,
                   int               E,
                   int               Tp,
                   int               knn,
                   int               tau,
                   double            theta,
                   int               exclusionRadius,
                   std::string       columns,
                   std::string       target,
                   std::string       smapFile,
                   std::string       jacobians,
                   bool              embedded,
                   bool              const_predict,
                   bool              verbose,
                   std::vector<bool> validLib );

Argument list in RcppEDMCommon.cpp:

auto SMapArgs = r::List::create(
    r::_["pathIn"]          = std::string("./"),
    r::_["dataFile"]        = std::string("./"),
    r::_["dataFrame"]       = r::DataFrame(),
    r::_["pathOut"]         = std::string("./"),
    r::_["predictFile"]     = std::string(""),
    r::_["lib"]             = std::string(""),
    r::_["pred"]            = std::string(""),
    r::_["E"]               = 0,
    r::_["Tp"]              = 1,
    r::_["knn"]             = 0,
    r::_["tau"]             = -1,
    r::_["theta"]           = 0,
    r::_["exclusionRadius"] = 0,
    r::_["columns"]         = std::string(""),
    r::_["target"]          = std::string(""),
    r::_["smapFile"]        = std::string(""),
    r::_["jacobians"]       = std::string(""),
    r::_["embedded"]        = false,
    r::_["const_predict"]   = false,
    r::_["verbose"]         = false,
    r::_["validLib"]        = std::vector<bool>() );   // <== This is reported as the error

Mapping in RcppEDMCommon.cpp:

//-------------------------------------------------------------------------
// Export / map the functions
//   First argument:  R function name, see ../R/EDM.R
//   Second argument: pointer to Rcpp interface function
//   Third argument:  arguments of the R function that encapsulates the
//                    C++ function in a Rcpp::List
//-------------------------------------------------------------------------
RCPP_MODULE(EDMInternal) {
    r::function( "RtoCpp_Simplex",       &Simplex_rcpp,    SimplexArgs       );
    r::function( "RtoCpp_SMap",          &SMap_rcpp,       SMapArgs          );
}

C++ API function call (overloaded) to core library from function SMap_rcpp() in SMap.cc (C++ API prototype listed below):

//----------------------------------------------------------
//
//----------------------------------------------------------
r::List SMap_rcpp( std::string       pathIn,
                   std::string       dataFile,
                   r::DataFrame      dataFrame,
                   std::string       pathOut,
                   std::string       predictFile,
                   std::string       lib,
                   std::string       pred,
                   int               E,
                   int               Tp,
                   int               knn,
                   int               tau,
                   double            theta,
                   int               exlusionRadius,
                   std::string       columns,
                   std::string       target,
                   std::string       smapFile,
                   std::string       jacobians,
                   bool              embedded,
                   bool              const_predict,
                   bool              verbose,
                   std::vector<bool> validLib ) {

    SMapValues SM;

    if ( dataFile.size() ) {
        // dataFile specified, dispatch overloaded SMap, ignore dataFrame
       
        SM = SMap( pathIn,
                   dataFile,
                   pathOut,
                   predictFile,
                   lib,
                   pred,
                   E,
                   Tp,
                   knn,
                   tau,
                   theta,
                   exlusionRadius,
                   columns,
                   target,
                   smapFile,
                   jacobians,
                   embedded,
                   const_predict,
                   verbose,
                   validLib );
    }
    else if ( dataFrame.size() ) {
        DataFrame< double > dataFrame_ = DFToDataFrame( dataFrame );

        SM = SMap( dataFrame_,
                   pathOut,
                   predictFile,
                   lib,
                   pred,
                   E,
                   Tp,
                   knn,
                   tau,
                   theta,
                   exlusionRadius,
                   columns,
                   target,
                   smapFile,
                   jacobians,
                   embedded,
                   const_predict,
                   verbose,
                   validLib );
    }
    else {
        Rcpp::warning( "SMap_rcpp(): Invalid input.\n" );
    }
   
    r::DataFrame df_pred = DataFrameToDF( SM.predictions  );
    r::DataFrame df_coef = DataFrameToDF( SM.coefficients );
    r::List output = r::List::create( r::Named("predictions")  = df_pred,
                                      r::Named("coefficients") = df_coef );

    return output;
}

As far as I can tell, the function arguments match the definition.  Again, this same code is implemented in another function where there is no issue.

An interesting feature of the error log is a "countdown" of function arguments, variously providing notes, until the final note and error exit:

candidate expects 0 arguments, 21 provided
candidate expects 1 argument, 21 provided
...
candidate expects 20 arguments, 21 provided


--  Error Log --

> R CMD build .
* checking for file ‘./DESCRIPTION’ ... OK
* preparing ‘rEDM’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* installing the package to build vignettes
      -----------------------------------
* installing *source* package ‘rEDM’ ...
** using staged installation
** libs
...

g++ -std=gnu++11 -I"/usr/share/R/include" -DNDEBUG -I ./cppEDM/src/ -I'/usr/local/lib/R/site-library/Rcpp/include' -I'/usr/local/lib/R/site-library/RcppThread/include'    -fpic  -g -O2 -fdebug-prefix-map=/build/r-base-tbZjLv/r-base-4.1.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c RcppEDMCommon.cpp -o RcppEDMCommon.o
RcppEDMCommon.cpp:60:51: error: no matching function for call to ‘Rcpp::Vector<19>::create(Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<Rcpp::DataFrame_Impl<Rcpp::PreserveStorage> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<int>, Rcpp::traits::named_object<int>, Rcpp::traits::named_object<int>, Rcpp::traits::named_object<int>, Rcpp::traits::named_object<int>, Rcpp::traits::named_object<int>, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<std::__cxx11::basic_string<char> >, Rcpp::traits::named_object<bool>, Rcpp::traits::named_object<bool>, Rcpp::traits::named_object<bool>, Rcpp::traits::named_object<std::vector<bool> >)’
   60 |     r::_["validLib"]        = std::vector<bool>() );
      |                                                   ^
In file included from /usr/local/lib/R/site-library/Rcpp/include/Rcpp/Vector.h:52,
                 from /usr/local/lib/R/site-library/Rcpp/include/Rcpp.h:40,
                 from RcppEDMCommon.h:10,
                 from RcppEDMCommon.cpp:14:
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:1122:19: note: candidate: ‘static Rcpp::Vector<RTYPE, StoragePolicy> Rcpp::Vector<RTYPE, StoragePolicy>::create() [with int RTYPE = 19; StoragePolicy = Rcpp::PreserveStorage]’
 1122 |     static Vector create(){
      |                   ^~~~~~
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:1122:19: note:   candidate expects 0 arguments, 21 provided
...

In file included from /usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:1126,
                 from /usr/local/lib/R/site-library/Rcpp/include/Rcpp/Vector.h:52,
                 from /usr/local/lib/R/site-library/Rcpp/include/Rcpp.h:40,
                 from RcppEDMCommon.h:10,
                 from RcppEDMCommon.cpp:14:
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/generated/Vector__create.h:70:16: note: candidate: ‘template<class T1> static Rcpp::Vector<RTYPE, StoragePolicy> Rcpp::Vector<RTYPE, StoragePolicy>::create(const T1&) [with T1 = T1; int RTYPE = 19; StoragePolicy = Rcpp::PreserveStorage]’
   70 |  static Vector create(const T1& t1){
      |                ^~~~~~
/usr/local/lib/R/site-library/Rcpp/include/Rcpp/generated/Vector__create.h:70:16: note:   template argument deduction/substitution failed:
RcppEDMCommon.cpp:60:51: note:   candidate expects 1 argument, 21 provided
...

/usr/local/lib/R/site-library/Rcpp/include/Rcpp/generated/Vector__create.h:1159:16: note:   template argument deduction/substitution failed:
RcppEDMCommon.cpp:60:51: note:   candidate expects 20 arguments, 21 provided
   60 |     r::_["validLib"]        = std::vector<bool>() );
      |                                                   ^
make: *** [/usr/lib/R/etc/Makeconf:177: RcppEDMCommon.o] Error 1
ERROR: compilation failed for package ‘rEDM’
* removing ‘/tmp/RtmpWluzdI/Rinst8d5e56742eb9/rEDM’
      -----------------------------------
ERROR: package installation failed

-- Version Info --

> sessionInfo()
R version 4.1.0 (2021-05-18)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.1 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C             
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8   
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8  
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                
 [9] LC_ADDRESS=C               LC_TELEPHONE=C           
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C      

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base    

other attached packages:
[1] Rcpp_1.0.5

loaded via a namespace (and not attached):
[1] compiler_4.1.0


-- C++ API prototype --

// SMap is a special case since it can be called with a function pointer
// to the SVD solver. This is done so that interfaces such as pybind11
// can provide their own object for the solver.
// 1) Data path/file with default SVD (LAPACK) assigned in Smap.cc 2)
SMapValues SMap( std::string pathIn          = "./data/",
                 std::string dataFile        = "",
                 std::string pathOut         = "./",
                 std::string predictFile     = "",
                 std::string lib             = "",
                 std::string pred            = "",
                 int         E               = 0,
                 int         Tp              = 1,
                 int         knn             = 0,
                 int         tau             = -1,
                 double      theta           = 0,
                 int         exclusionRadius = 0,
                 std::string columns         = "",
                 std::string target          = "",
                 std::string smapFile        = "",
                 std::string derivatives     = "",
                 bool        embedded        = false,
                 bool        const_predict   = false,
                 bool        verbose         = true,
                 std::vector<bool> validLib  = std::vector<bool>() );

// 2) DataFrame with default SVD (LAPACK) assigned in Smap.cc 2)
SMapValues SMap( DataFrame< double > &dataFrameIn,
                 std::string pathOut         = "./",
                 std::string predictFile     = "",
                 std::string lib             = "",
                 std::string pred            = "",
                 int         E               = 0,
                 int         Tp              = 1,
                 int         knn             = 0,
                 int         tau             = -1,
                 double      theta           = 0,
                 int         exclusionRadius = 0,
                 std::string columns         = "",
                 std::string target          = "",
                 std::string smapFile        = "",
                 std::string derivatives     = "",
                 bool        embedded        = false,
                 bool        const_predict   = false,
                 bool        verbose         = true,
                 std::vector<bool> validLib  = std::vector<bool>() );


_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to