Search code examples
rcpp

Rcpp modules: Validator function for exposed constructors with same number of parameters


I would like to expose a C++ class with Rcpp modules that has two constructors with the same number of parameters. As documented in the Rcpp modules vignette, this can be achieved by using a validator function as the second argument to .constructor with the type

typedef bool (*ValidConstructor)(SEXP*,int);

Could somebody provide an example of how it is supposed to be used? In the vignette, there is only a TODO note that an example should be included there.


Solution

  • With the disclaimer that I haven't personally used this before, the following appears to work:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    class Example {
    public:
        Example(int x_, int y_)
            : x(x_), y(y_)
        {
            Rcout << __PRETTY_FUNCTION__ << "\n";
        }
    
        Example(std::string x_, std::string y_)
            : x(x_.size()), y(y_.size())
        {
            Rcout << __PRETTY_FUNCTION__ << "\n";
        }
    
        int add() const
        { return x + y; }
    
    private:
        int x, y;
    };
    
    bool validate_int_int(SEXP* args, int nargs)
    { return TYPEOF(args[0]) == INTSXP && TYPEOF(args[1]) == INTSXP; }
    
    bool validate_string_string(SEXP* args, int nargs)
    { return TYPEOF(args[0]) == STRSXP && TYPEOF(args[1]) == STRSXP; }
    
    RCPP_MODULE(ExampleMod) {
    
        class_<Example>("Example")
            .constructor<int, int>(
                "(int, int) constructor",
                validate_int_int
            )
            .constructor<std::string, std::string>(
                "(string, string) constructor",
                validate_string_string
            )
            .method("add", &Example::add)
        ;
    }
    

    Testing from R,

    ex.int <- new(Example, 1L, 2L)
    # Example::Example(int, int)
    
    ex.string <- new(Example, "one", "two")
    # Example::Example(std::string, std::string)
    
    ex.int$add()
    # [1] 3
    
    ex.string$add()
    # [1] 6 
    

    In each of validate_int_int and validate_string_string we are just testing the input SEXP types against the signatures of their corresponding constructors.