Please note that this is the "in progress" section of modules, so things can change.

There are probably open questions. e.g. at the moment you have to deal with who is responsible for the pointers.

Le 03/04/13 22:12, Romain Francois a écrit :
Hi,

Fasten your seatbelts.

First, the problem is definitely object slicing. The best resource I
know about to explain it is a chapter of Scott Meyers "Effective C++".
Robin, I would highly recommend that you get it. Specially considering
that you are willing to get your hands dirty.

Anyway, I would suggest that your MyfatherList_ is a vector of father
pointers:

std::vector<father*> MyfatherList_;

if you use any kind of object, even smart pointers, you'll get slicing.


Then, you need to have a virtual destructor on the father class and make
the WhoAmI methods virtual. This is how you do inheritance in C++.

class father
{
   public:
     virtual ~father(){};
     father(){};
     father(father const & x) {};
     virtual void WhoAmI() const{
       Rcout<<"father"<<endl;
     };
};

class children1_t : public father
{

   public:
     ~children1_t(){};
     children1_t(){};
     children1_t(children1_t const & x){};
     virtual void WhoAmI() const{
       Rcout<<"son1"<<endl;
     };
};

This is very basic C++ inheritance stuff.



The vector class looks like this:

class vector_Of_father {

   public:
     std::vector<father*> MyfatherList_;
     ~vector_Of_father(){};
     vector_Of_father() : MyfatherList_(){};

     father* vec_get( int i) { return MyfatherList_.at(i); };

     void WhoAmI(int i) const {
         MyfatherList_[i]->WhoAmI();
     };
     int size(){ return(MyfatherList_.size()); };

     void push_back(object<father> func){
         MyfatherList_.push_back(func);
     };

};

Some comments.
- As I said above, you are storing a vector of pointers.
- that makes the implementation of WhoAmI, size simple.
- for get_vec, you can just return a pointer to a father. We support this.
- for push_back, you need to use object<father>, that is just a
disguised pointer. just using father* would require declaring how to
handle it. We don't support this yet (for some definition of yet).
Anyway, you can just see object<T> as T*


Now the module code.

RCPP_MODULE(mod_example2){

   class_<father>( "father" )
     .constructor()
     .method("WhoAmI",&father::WhoAmI)
     ;

   class_<children1_t>( "children1_t" )
     .derives<father>("father" )
     .constructor()
     ;

   class_<children2_t>( "children2_t" )
     .derives<father>("father" )
     .constructor()
     ;

   class_<vector_Of_father>( "vector_Of_father")
     .constructor()
     .method( "size", &vector_Of_father::size)
     .method( "WhoAmI",&vector_Of_father::WhoAmI )
     .method( "push_back", &vector_Of_father::push_back )
     .method("[[",&vector_Of_father::vec_get)
   ;

}

That's it. You don't need to redefine WhoAmI for children classes. The
.derives makes it for you.

And with this:

res <- new( vector_Of_father )
res$push_back(new( father ))
res$push_back(new( children1_t ))
res$push_back(new( children2_t ))
res$WhoAmI(2)
res$WhoAmI(1)
res$WhoAmI(0)
res[[2]]$WhoAmI()
res[[1]]$WhoAmI()
res[[0]]$WhoAmI()

I do get:

son2
son1
father
son2
son1
father




Here is the full code of the .cpp file:

#include <Rcpp.h>

using namespace std;
using namespace Rcpp;

class father ;
class children1_t;
class children2_t ;
class vector_Of_father;

RCPP_EXPOSED_CLASS(father)
RCPP_EXPOSED_CLASS(children1_t)
RCPP_EXPOSED_CLASS(children2_t)
RCPP_EXPOSED_CLASS(vector_Of_father)

class father
{
   public:
     virtual ~father(){};
     father(){};
     father(father const & x) {};
     virtual void WhoAmI() const{
       Rcout<<"father"<<endl;
     };
};

class children1_t : public father
{

   public:
     ~children1_t(){};
     children1_t(){};
     children1_t(children1_t const & x){};
     virtual void WhoAmI() const{
       Rcout<<"son1"<<endl;
     };
};

class children2_t : public father
{
   public:
     ~children2_t(){};
     children2_t(){};
     children2_t(children2_t const & x){};
     virtual void WhoAmI() const{
       Rcout<<"son2"<<endl;
     };
};


class vector_Of_father {

   public:
     std::vector<father*> MyfatherList_;
     ~vector_Of_father(){};
     vector_Of_father() : MyfatherList_(){};

     father* vec_get( int i) { return MyfatherList_.at(i); };

     void WhoAmI(int i) const {
         MyfatherList_[i]->WhoAmI();
     };
     int size(){ return(MyfatherList_.size()); };

     void push_back(object<father> func){
         MyfatherList_.push_back(func);
     };

};


RCPP_MODULE(mod_example2){

   class_<father>( "father" )
     .constructor()
     .method("WhoAmI",&father::WhoAmI)
     ;

   class_<children1_t>( "children1_t" )
     .derives<father>("father" )
     .constructor()
     ;

   class_<children2_t>( "children2_t" )
     .derives<father>("father" )
     .constructor()
     ;

   class_<vector_Of_father>( "vector_Of_father")
     .constructor()
     .method( "size", &vector_Of_father::size)
     .method( "WhoAmI",&vector_Of_father::WhoAmI )
     .method( "push_back", &vector_Of_father::push_back )
     .method("[[",&vector_Of_father::vec_get)
   ;

}

Romain


Le 03/04/13 18:43, Robin Girard a écrit :
I am still working on my vector of a class father with inheritance
(polymorphic subclasses ?). I created an exemple below that works fine
but I face the known problem of "slicing" as named here :
http://stackoverflow.com/questions/10154977/c-vector-with-inheritance
and fail to implement the proposed solution.

I have 2 tried 2 things and ended up with 2 questions:

Question 1 -  I tryed the solution proposed in the link with
make_shared and shared_ptr. I had to add PKG_CXXFLAGS=-g -std=c++0x
since my MinGW compiler did not find any -std=c++11.  I got no
compilation error but when I run the code it slices my children class :

res=new("Rcpp_vector_Of_father")
res$push_back(new("Rcpp_father"))
res$push_back_children1_t(new("Rcpp_children1_t"))
res$WhoAmI(1)
father
res$WhoAmI(0)
father

res[[1]]$WhoAmI()
father
res[[0]]$WhoAmI()
father


Question 2 - I tryed a solution with XPtr (although I'm not sure how
this works) and got the following error at the module compilation
example_mod_consumption.cpp: In member function 'void
vector_Of_father::push_back_children1_t(children1_t)':
example_mod_consumption.cpp:80:53: error: no matching function for
call to 'std::vector<Rcpp::XPtr<father>
>::push_back(Rcpp::XPtr<children1_t>)'

XPtr<father> has no relationship with XPtr<children1_t>. They are
independant classes generated by the XPtr template class. They don't
know about the inheritance.

below are the code for the two approach and at the end the code of the
module.



-------------------- Solution with XPtr

#include <Rcpp.h>

using namespace std;
using namespace Rcpp;

class father ;
class children1_t;
class children2_t ;
class vector_Of_father;

RCPP_EXPOSED_CLASS(father)
RCPP_EXPOSED_CLASS(children1_t)
RCPP_EXPOSED_CLASS(children2_t)
RCPP_EXPOSED_CLASS(vector_Of_father)

class father
{
   public:
     ~father(){};
     father(){};
     father(father const & x) {};
     void WhoAmI() const{
       Rcout<<"father"<<endl;
     };
};

class children1_t : public father
{

   public:
     ~children1_t(){};
     children1_t(){};
     children1_t(children1_t const & x){};
     void WhoAmI() const{
       Rcout<<"son1"<<endl;
     };
};

class children2_t : public father
{
   public:
     ~children2_t(){};
     children2_t(){};
     children2_t(children2_t const & x){};
         void WhoAmI() const{
       Rcout<<"son2"<<endl;
     };
};


class vector_Of_father {

   public:
     std::vector<XPtr<father> > MyfatherList_;
     //std::vector<shared_ptr<father> > MyfatherList_;
     ~vector_Of_father(){};
     vector_Of_father() : MyfatherList_(){};
    father vec_get( int i) { return(*(MyfatherList_.at(i))); };

    void WhoAmI(int i) const
    {
        MyfatherList_[i]->WhoAmI();
    };
    int size(){ return(MyfatherList_.size()); };

    void push_back(father func){
        MyfatherList_.push_back(XPtr<father>(&func));
    };

    void push_back_children1_t(children1_t func){
        MyfatherList_.push_back(XPtr<children1_t>(&func));
    };
};

-------------------- Solution with make_shared and shared_ptr

only the class vector_of_father is different also #include <memory> is
added after Rcpp.h include.

class vector_Of_father {

   public:
     std::vector<shared_ptr<father> > MyfatherList_;
     ~vector_Of_father(){};
     vector_Of_father() : MyfatherList_(){};

   father vec_get( int i) { return(*(MyfatherList_.at(i))); };

   void WhoAmI(int i) const
   {
     MyfatherList_[i]->WhoAmI();
   };
   int size(){ return(MyfatherList_.size()); };


   void push_back(father func){
     MyfatherList_.push_back(make_shared<father>(func));
   };
   void push_back_children1_t(children1_t func){
     MyfatherList_.push_back(make_shared<children1_t>(func));
   };
};



-------------- the module code

RCPP_MODULE(mod_example2){
   using namespace Rcpp;

   class_<father>( "father" )
    //constructors
      .constructor()
     .method("WhoAmI",&father::WhoAmI)
    ;

   class_<children1_t>( "children1_t" )
     .derives<father>("father" )
    //constructors
      .constructor()
     .method("WhoAmI",&children1_t::WhoAmI)
    ;

   class_<children2_t>( "children2_t" )
     .derives<father>("father" )
    //constructors
      .constructor()
     .method("WhoAmI",&children2_t::WhoAmI)
    ;

   class_<vector_Of_father>( "vector_Of_father")
     .constructor()
    // .constructor<int>()
     .method( "size", &vector_Of_father::size)
  // .method("capacity", &cplfunctionvec::capacity,"Return size of
allocated storage capacity. Returns the size of the storage space
currently allocated for the vector, expressed in terms of elements.")
//  .method( "max_size", &cplfunctionvec::max_size)
     .method( "WhoAmI",&vector_Of_father::WhoAmI )
     //.method( "test",&vector_Of_father::test )
     .method( "push_back", &vector_Of_father::push_back )

.method("push_back_children1_t",&vector_Of_father::push_back_children1_t)
//  .const_method( "at", &cplfunctionvec::at )
     .method("[[",&vector_Of_father::vec_get)
   //  .method("[[<-",&vector_Of_father::vec_set)
   ;

}


Dr. Girard Robin
Chargé de Recherche

MINES-ParisTech / Département Energétique et Procédés / PERSEE /
Groupe ERSEI
Centre Procédés, Energies Renouvelables et Systèmes Energétiques (PERSEE)
Center for Processes, Renewables Energies and Energy Systems
Renewable Energies & Smartgrids (ERSEI)

1 Rue Claude Daunesse - CS 10207 - F-06904 Sophia Antipolis Cedex
Tel: +33.4.93.67.89.64 (~99), Fax: +33.4.93.95.75.35
e-mail : robin.gir...@mines-paristech.fr

web page perso http://www.mines-paristech.fr/Services/Annuaire/&?id=8828
statoverflow : http://stats.stackexchange.com/users/223/robin-girard
web page centre PERSEE : http://www.cep.mines-paristech.fr/
linkedin : http://www.linkedin.com/profile/view?id=14907272&trk=tab_pro




--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30

R Graph Gallery: http://gallery.r-enthusiasts.com

blog:            http://blog.r-enthusiasts.com
|- http://bit.ly/ZTFLDo : Simpler R help tooltips
`- http://bit.ly/YFsziW : R Help tooltips

_______________________________________________
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