[Rcpp-devel] Exposing constructors with same number of arguments with different types using Rcpp Modules
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