[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