There is a mechanism for dispatching to the appropriate constructor, but this needs extra work from you on the C++ side. I'm currently not entirely happy about it, and this might change in the future for something nicer.

Some information about it was posted on this thread:
http://article.gmane.org/gmane.comp.lang.r.rcpp/929/match=constructors

You essentially have to supply an extra function that decides if the constructor is appropriate for the arguments that are passed in:

So your example would become something like this:

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;
}

bool fun1( SEXP* args, int nargs){
    if( nargs != 2 ) return false ;
    if( TYPEOF(args[1]) == STRSXP ) return false ;
    return true ;
}
bool fun2( SEXP* args, int nargs){
    if( nargs != 2 ) return false ;
    if( TYPEOF(args[1]) != STRSXP ) return false ;
    return true ;
}

RCPP_MODULE(unif_module) {
    class_<Uniform>( "Uniform" )

    .constructor<double,double>("", &fun1 )
    .constructor<double,std::string>("", &fun2)
    .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) )
Uniform <- unif_module$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 )


Romain


Le 13/05/11 16:35, Jelmer Ypma a écrit :
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
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@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel



--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
http://romain-francois.com
|- http://bit.ly/hdKhCy : Rcpp article in JSS
|- http://bit.ly/elZJRJ : Montpellier Comedie Club - Avril 2011
`- http://bit.ly/fhqbRC : Rcpp workshop in Chicago on April 28th


_______________________________________________
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