[Rcpp-devel] Exposing constructors with same number of arguments with different types using Rcpp Modules

Jelmer Ypma jelmerypma at gmail.com
Fri May 13 21:27:49 CEST 2011


Hi Dirk,

many thanks for your quick reply. Maybe something like the below could
work? The different constructor specifications are defined in the list
ClassName at constructors, but I coudln't find where R decides which of
these functions to call.

Thanks again,
Jelmer

overloaded.func <- function( x1, x2 ) {
    f1 <- function( x1, x2 ) {
        cat( "f1\n" )
        return( x1 + x2 )
    }

    f2 <- function( x1, x2 ) {
        cat( "f2\n" )
        return( nchar(x1) + nchar(x2) )
    }

    f3 <- function( x1, x2 ) {
        cat( "f3\n" )
        return( x1 + nchar(x2) )
    }

    f4 <- function( x1, x2 ) {
        cat( "f4\n" )
        return( x1 + x2 )
    }

    # add different versions to list
    func.list <- list( f1, f2, f3, f4 )

    # define argument types of f1, f2, f3
    argstypes <- list(
        c( "numeric", "numeric" ),          # input arguments of f1
        c( "character", "character" ),      # input arguments of f2
        c( "numeric", "character" ),        # input arguments of f3
        c( "numeric", "integer" ) )         # input arguments of f4

    # get types of input arguments supplied by user
    inputtypes <- c( class( x1 ), class( x2 ) )

    # get index of function that agrees with these arguments
    findex <- which( sapply( argstypes, function(type) {
all(inputtypes == type) } ) )

    # if there is such a function evalute it, otherwise return error
    if( length( findex ) == 0 ) {
        stop(paste( inputtypes, sep=' '  ))
    }
    else {
        return( func.list[[ findex ]]( x1, x2 ) )
    }
}


overloaded.func( 3, 3 )             # f1
overloaded.func( "test", "test" )   # f2
overloaded.func( 3, "test" )        # f3
overloaded.func( 2, 3L )            # f4
overloaded.func( "test", 3 )        # error




On Fri, May 13, 2011 at 18:58, Dirk Eddelbuettel <edd at debian.org> wrote:
>
> Hi Jelmer,
>
> On 13 May 2011 at 16:35, Jelmer Ypma wrote:
> | Dear Rcpp-list,
> |
> | I'm trying to expose multiple constructors of a C++ class to R using
> | modules. Here is an example of what I want to do based on the Uniform
> | example
> |
> | ===Begin: example
> | library('inline')
> | library('Rcpp')
> |
> | test_code <-'
> | using namespace Rcpp;
> |
> | class Uniform {
> |     public:
> |         Uniform(double min_, double max_) : min(min_), max(max_) {}
> |         Uniform(double max_, std::string dummy_) : min(0.0), max(max_)
> | { Rprintf("%s\\n", dummy_.c_str()); }
> |         Uniform(double max_ ) : min(0.0), max(max_) {}
> |
> |         NumericVector draw(int n) const {
> |             RNGScope scope;
> |             return runif( n, min, max );
> |         }
> |
> |         double min, max;
> | };
> |
> | double range( Uniform* w) {
> |     return w->max - w->min;
> | }
> |
> | RCPP_MODULE(unif_module) {
> |     class_<Uniform>( "Uniform" )
> |
> |     .constructor<double,double>()
> |     .constructor<double,std::string>()
> |     .constructor<double>()
> |
> |     .field( "min", &Uniform::min )
> |     .field( "max", &Uniform::max )
> |
> |     .method( "draw", &Uniform::draw )
> |     .method( "range", &range )
> |     ;
> | }
> | '
> |
> | fx <- cxxfunction( signature(), "" , include = test_code, plugin = "Rcpp" )
> | unif_module <- Module( "unif_module", getDynLib(fx) )
> |
> | show( Uniform )
> | u1 <- new( Uniform, 0, 10 )
> | u1$min
> | u1$max
> | u1$range()
> | u1$draw( 10L )
> |
> | u2 <- new( Uniform, 10, "test" )
> | u2$min
> | u2$max
> | u2$range()
> | u2$draw( 10L )
> |
> | u3 <- new( Uniform, 10 )
> | u3$min
> | u3$max
> | u3$range()
> | u3$draw( 10L )
> | ===End: example
> |
> | Compilation works fine (on Windows using RTools, Rcpp_0.9.4.1,
> | inline_0.3.8), but the R code cannot distinguish between two
> | constructors with the same number of arguments, but with different
> | types for the arguments and always calls Uniform(double, double). The
>
> If I recall correctly, we have determined that this cannot work. It is one of
> these 'obvious in hindsight' issue.  Recall that R does the dispatch, and R
> cannot differentiate between  foo(double) and  foo(int)  as it is not typed.
>
> So I think you will have to differentiate the constructors by name. Sorry
> about that, but even Rcpp modules has its limits.
>
> And I may of course be wrong too in which case Romain may come in and
> clarify.
>
> Hope this helps,  Dirk
>
> | output I get is as follows:
> |
> | > unif_module <- Module( "unif_module", getDynLib(fx) )
> |
> | > show( Uniform )
> | C++ class 'Uniform' <02748CF0>
> | Constructors:
> |     Uniform(double, double)
> |     Uniform(double, std::string)
> |     Uniform(double)
> |
> | Fields:
> |     double max
> |     double min
> |
> | Methods:
> |      Rcpp::NumericVector draw(int)  const
> |
> |      double range()
> |
> |
> | > u1 <- new( Uniform, 0, 10 )
> |
> | > u1$min
> | [1] 0
> |
> | > u1$max
> | [1] 10
> |
> | > u1$range()
> | [1] 10
> |
> | > u1$draw( 10L )
> |  [1] 6.330045 4.637002 6.507183 4.192280 9.560602 3.927548 4.399107
> | 2.332956 8.810553 3.864929
> |
> | > u2 <- new( Uniform, 10, "test" )
> | Error in new_CppObject_xp(fields$.module, fields$.pointer, ...) :
> |   not compatible with REALSXP
> |
> |
> | Does anyone know of a workaround for this?
> |
> | Many thanks in advance!
> | Jelmer
> | _______________________________________________
> | Rcpp-devel mailing list
> | Rcpp-devel at lists.r-forge.r-project.org
> | https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>
> --
> Gauss once played himself in a zero-sum game and won $50.
>                      -- #11 at http://www.gaussfacts.com
>


More information about the Rcpp-devel mailing list