Message-ID: <CAO7JsnTDnAG-ZDCzpeVsNBn9qjEa3Fu3aX3NQaK70eGEir8KGA@mail.gmail.com>
Date: 2012-02-16T16:25:39Z
From: Douglas Bates
Subject: [Rcpp-devel] Problem with the copy constructor of Rcpp::S4
In-Reply-To: <9C9316AF-E17F-4ECE-9C1E-D0A8131F9BF9@math.univ-lille1.fr>
On Thu, Feb 16, 2012 at 9:25 AM, R?mi Lebret
<remi.lebret at math.univ-lille1.fr> wrote:
> Hi,
>
> I've got some issues by using the copy constructor of the S4 class.
>
> I want to make a copy of a S4 object but it looks like the copy constructor
> returns a reference instead of a new instance of the S4 class.
>
> I made a dummy example to illustrate my problem:
>
> ##############################################################
> setClass(
> ? Class="ResultObject",
> ? representation=representation(
> ? ? data = "numeric"
> ? ),
> ? prototype=prototype(
> ? ? data = numeric(0)
> ? )
> )
> ##############################################################
>
> ##############################################################
> setClass(
> ? Class="TestObject",
> ? representation=representation(
> ? ? size = "numeric",
> ? ? results = "ResultObject"
> ? ),
> ? prototype=prototype(
> ? ? size = numeric(0),
> ? ? results = new("ResultObject")
> ? )
> )
> ##############################################################
>
>
> ##############################################################
> src <- '
> ? Rcpp::S4 obj(S4Object);
> ? // get the size
> ? int n = obj.slot("size");
> ? // get a copy of the ResultObject by calling the copy constructor
> ? // --> but here it looks like a reference not a copy ?
> ? Rcpp::S4 res(obj.slot("results"));
>
> ? // if size is greater than create a list of results
> ? if ( n > 1 ){
> ? ? // create a new list
> ? ? Rcpp::List resList(n);
> ? ? // loop over the results
> ? ? for (int i=0; i<n; i++ ){
> ? ? ? // save results into the S4 object
> ? ? ? res.slot("data") = i;
> ? ? ? // copy the S4 object into the list -->? so it looks like a copy of a
> reference here...
> ? ? ? resList[i]=res;
> ? ? }
> ? ? // set the list to our S4 object
> ? ? obj.slot("results") = resList;
> ? }
> ? // otherwise store only one result
> ? else if ( n == 1 ){
> ? ? res.slot("data") = 1;
> ?? ? obj.slot("results") = res;
> ? }
> ? // return the S4 object
> ? return obj;
> '
>
> testList <- cxxfunction(signature(S4Object="TestObject"), src, plugin =
> "Rcpp")
> ##############################################################
>
> # test with 3 elements
> # all data slot will contain the same value, that's not what we expect
> test1<-new("TestObject", size=3)
> testList(test1)
>
> # test with only one element
> test2<-new("TestObject", size=1)
> testList(test2)
>
>
>
> Any idea how to make a copy of a S4 object?
You probably want to clone the object, not use the copy constructor.
That is, (not tested)
Rcpp::S4 res(Rcpp::clone(obj.slot("results"));