[Rcpp-devel] Problem exposing inherited member function of derived class to R through RCPP_MODULE

Luke.Domanski at csiro.au Luke.Domanski at csiro.au
Tue Oct 1 00:08:04 CEST 2013


Hi All,

Just a comment on a side effect/issue with my previously posted solution to this problem, i.e.:

> you can also solve the problem by overwriting the
> inherited members in the derived class such that they trivially call
> the base class implementation. As described briefly in my original
> email.

Like follows:

Class A {
	public:
		void fun2(){ };
		void fun1(){ fun2(); };
}

Class A_derived : public A {
	public:
		void fun2(){ };
		void fun1(){ A::fun1(); };
}

RCPP_MODULE(testing) {
      class_<A_derived>("A_derived")
      .method("fun1", &A_derived::fun1)
      ;
}

The issue here is that the call tree under A::fun1() will only call functions of the base class unless they are defined virtual, so any functions you re implement in the derived class are ignored. In the above example, this means A::fun2() is called from A::fun1() instead of A_derived::fun2(). A::fun2() must be declared as virtual for A_derived::fun2() to be called from A::fun1().

If for some reason you cannot make A::fun2() virtual (e.g. fun2 need to be a template), you can just create a wrapper function in the derived class and expose this to R with its name changed to the function being wrapped. E.g.

I am not sure how to overcome this problem if (for some reason) you cannot use a virtual function, e.g. fun2 is a template function.

Cheers,
Luke Domanski
 

> Excellent,
> 
> Thanks Romain.
> 
> Re. code posted at https://gist.github.com/romainfrancois/6695921:
> In the real code I extend "A_derived" with other functionality, not
> just inherit into it, but this typedef trick will be enough to get me
> started. Thanks. I will have to brush up on my C++ some more and see if
> it is possible to add this functionality within the typedef
> syntax/mechanism, such that the resulting type still acts like a true
> class.
> 
> To others reading, you can also solve the problem by overwriting the
> inherited members in the derived class such that they trivially call
> the base class implementation. As described briefly in my original
> email.
> 
> Luke.
> 
> 
> > -----Original Message-----
> >
> > Hello,
> >
> > Due to the way modules are currently implemented, what goes in .field
> > and .method must be member of the actual class, not inherited. I'm
> not
> > sure how to express it otherwise.
> >
> > So instead of using public inheritance as you do in:
> >
> > class A_derived : public A<B_derived> {};
> >
> > You can use a typedef. See the code in this gist:
> > https://gist.github.com/romainfrancois/6695921
> >
> > Romain
> >
> > Le 25/09/13 06:30, Luke.Domanski at csiro.au a écrit :
> > > Hi All,
> > >
> > > Thanks for your previous help on
> > > http://comments.gmane.org/gmane.comp.lang.r.rcpp/5972
> > >
> > > I have been able to implement an RCPP_MODULE of the "real code"
> > > containing classes represented by classes A and B in the above
> > thread.
> > > That set/group of classes implements a generic base class that will
> > be
> > > extended from to provide particular functionality.
> > >
> > > I now wish to expose via RCPP_MODULE a class A_derived which
> derives
> > > from A<B_derived>. I want to expose member variable var1 and
> > > function
> > > fun1 of class A_derived which are both inherited from A<B_derived>.
> > i.e.
> > > no overwriting definition of A_derived::var1 or A_derived::fun1
> > exist,
> > > only A<B_derived>::var1 and A<B_derived>::fun1.
> > >
> > > However, the following RCPP_MODULE definition produces the
> > > subsequent compiler error.
> > >
> > > RCPP_MODULE(testing) {
> > >
> > >      class_<A_derived>("A_derived")
> > >
> > >      .field( "var1", &A_derived::var1)
> > >
> > >      .method("fun1", &A_derived::fun1)
> > >
> > >      ;
> > >
> > > }
> > >
> > > test2.cpp: In function 'void _rcpp_module_testing_init()':
> > >
> > > test2.cpp:33:37: error: no matching function for call to
> > > 'Rcpp::class_<A_derived>::field(const char [5], double
> > A<B_derived>::*)'
> > >
> > > test2.cpp:33:37: note: candidate is:
> > >
> > > C:/.../R/win-
> > library/3.0/Rcpp/include/Rcpp/module/Module_Field.h:68:7:
> > > note: template<class T> Rcpp::class_<Class>::self&
> > > Rcpp::class_::field(const char*, T Class::*, const char*) [with T =
> > T,
> > > Class = A_derived, Rcpp::class_<Class>::self =
> > > Rcpp::class_<A_derived>]
> > >
> > > It seems the compiler is converting A_derived::var1 and fun1 into
> > > their true references A<B_derived>::var1 and fun1, but the Rcpp
> > > templates cannot handle the situation where the referenced variable
> > or
> > > function is not a "proper" member of the class.
> > >
> > > However, the error goes away if overwrite var1 and fun1 in
> > > A_derived, and implement A_derived::fun1() as:
> > >
> > > void A_derived::fun1() {
> > >
> > >      A<B_derived>::fun1();
> > >
> > > };
> > >
> > > This is not ideal.
> > >
> > > Can someone please help me formulate the correct RCPP_MODULE
> > definition?
> > > Is there something that I am doing wrong, or have I once again
> > > triggered a chain of the template meta program that is not
> > implemented in Rcpp.
> > >
> > > Full code and error reduct follows:
> > >
> > > -----test2.cpp-----
> > >
> > > #include <RcppCommon.h>
> > >
> > > class B {
> > >
> > >      public:
> > >
> > >          B (SEXP b);
> > >
> > > };
> > >
> > > template <class T> class A {
> > >
> > >      public:
> > >
> > >          double var1;
> > >
> > >          void fun1();
> > >
> > > };
> > >
> > > class B_derived : public B {
> > >
> > >      public:
> > >
> > >          B_derived(SEXP b);
> > >
> > > };
> > >
> > > class A_derived : public A<B_derived> {};
> > >
> > > #include <Rcpp.h>
> > >
> > > B::B(SEXP b) {};
> > >
> > > template <class T> void A<T>::fun1(){
> > >
> > >      Rcpp::Rcout << "Object of Type: " << typeid(this).name() <<
> > "\n";
> > >
> > > }
> > >
> > > B_derived::B_derived(SEXP b) : B::B(b) {};
> > >
> > > using namespace Rcpp;
> > >
> > > RCPP_MODULE(testing) {
> > >
> > >      class_<A_derived>("A_derived")
> > >
> > >      .field( "var1", &A_derived::var1)
> > >
> > >      .method("fun1", &A_derived::fun1)
> > >
> > >      ;
> > >
> > > }
> > >
> > > ----end test2.cpp----
> > >
> > >  > require(R)
> > >
> > >  > sourceCpp(file="test2.cpp", verbose=TRUE)
> > >
> > > ...snip...
> > >
> > > g++ -m32 -I"C:/PROGRA~1/R/R-30~1.1/include" -DNDEBUG
> > > -I"C:/.../R/win-library/3.0/Rcpp/include"
> > > -I"d:/RCompile/CRANpkg/extralibs64/local/include"     -O2 -Wall
> > > -mtune=core2 -c test2.cpp -o test2.o
> > >
> > > test2.cpp: In function 'void _rcpp_module_testing_init()':
> > >
> > > test2.cpp:33:37: error: no matching function for call to
> > > 'Rcpp::class_<A_derived>::field(const char [5], double
> > A<B_derived>::*)'
> > >
> > > test2.cpp:33:37: note: candidate is:
> > >
> > > C:/.../R/win-
> > library/3.0/Rcpp/include/Rcpp/module/Module_Field.h:68:7:
> > > note: template<class T> Rcpp::class_<Class>::self&
> > > Rcpp::class_::field(const char*, T Class::*, const char*) [with T =
> > T,
> > > Class = A_derived, Rcpp::class_<Class>::self =
> > > Rcpp::class_<A_derived>]
> > >
> > > make: *** [test2.o] Error 1
> > >
> > > Error in sourceCpp(file = "test2.cpp", verbose = TRUE) :
> > >
> > >    Error 1 occurred building shared library.
> > >
> > > Cheers,
> > >
> > > Luke Domanski.
> >
> >
> > --
> > Romain Francois
> > Professional R Enthusiast
> > +33(0) 6 28 91 30 30



More information about the Rcpp-devel mailing list