diff --git a/Makefile b/Makefile index 91261c66..4b85c9f1 100644 --- a/Makefile +++ b/Makefile @@ -10,11 +10,8 @@ test: all clean: @Rscript -e 'devtools::clean_dll()' + @Rscript -e 'devtools::clean_dll("cpp11test")' clang_format=`which clang-format` format: $(shell find . -name '*.hpp') $(shell find . -name '*.cpp') -ifeq ($(findstring version 10,$(shell ${clang_format} --version 2>/dev/null)),) - @echo "clang-format 10 is required" -else @${clang_format} -i $? -endif diff --git a/cpp11test/.Rbuildignore b/cpp11test/.Rbuildignore new file mode 100644 index 00000000..91114bf2 --- /dev/null +++ b/cpp11test/.Rbuildignore @@ -0,0 +1,2 @@ +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/cpp11test/R/cpp11.R b/cpp11test/R/cpp11.R index 3d6b0f5d..4b9a1d9a 100644 --- a/cpp11test/R/cpp11.R +++ b/cpp11test/R/cpp11.R @@ -8,30 +8,6 @@ data_frame_ <- function() { .Call(`_cpp11test_data_frame_`) } -my_stop <- function(mystring, myarg) { - invisible(.Call(`_cpp11test_my_stop`, mystring, myarg)) -} - -my_stop_n1 <- function(mystring) { - invisible(.Call(`_cpp11test_my_stop_n1`, mystring)) -} - -my_warning <- function(mystring, myarg) { - invisible(.Call(`_cpp11test_my_warning`, mystring, myarg)) -} - -my_warning_n1 <- function(mystring) { - invisible(.Call(`_cpp11test_my_warning_n1`, mystring)) -} - -my_message <- function(mystring, myarg) { - invisible(.Call(`_cpp11test_my_message`, mystring, myarg)) -} - -my_message_n1 <- function(mystring) { - invisible(.Call(`_cpp11test_my_message_n1`, mystring)) -} - my_stop_n1fmt <- function(mystring) { invisible(.Call(`_cpp11test_my_stop_n1fmt`, mystring)) } @@ -56,6 +32,30 @@ my_message_n2fmt <- function(mystring, myarg) { invisible(.Call(`_cpp11test_my_message_n2fmt`, mystring, myarg)) } +my_stop <- function(mystring, myarg) { + invisible(.Call(`_cpp11test_my_stop`, mystring, myarg)) +} + +my_stop_n1 <- function(mystring) { + invisible(.Call(`_cpp11test_my_stop_n1`, mystring)) +} + +my_warning <- function(mystring, myarg) { + invisible(.Call(`_cpp11test_my_warning`, mystring, myarg)) +} + +my_warning_n1 <- function(mystring) { + invisible(.Call(`_cpp11test_my_warning_n1`, mystring)) +} + +my_message <- function(mystring, myarg) { + invisible(.Call(`_cpp11test_my_message`, mystring, myarg)) +} + +my_message_n1 <- function(mystring) { + invisible(.Call(`_cpp11test_my_message_n1`, mystring)) +} + remove_altrep <- function(x) { .Call(`_cpp11test_remove_altrep`, x) } @@ -160,6 +160,34 @@ cpp11_safe_ <- function(x_sxp) { .Call(`_cpp11test_cpp11_safe_`, x_sxp) } +sum_dbl_for_ <- function(x) { + .Call(`_cpp11test_sum_dbl_for_`, x) +} + +sum_dbl_for2_ <- function(x_sxp) { + .Call(`_cpp11test_sum_dbl_for2_`, x_sxp) +} + +sum_dbl_for3_ <- function(x_sxp) { + .Call(`_cpp11test_sum_dbl_for3_`, x_sxp) +} + +sum_dbl_foreach_ <- function(x) { + .Call(`_cpp11test_sum_dbl_foreach_`, x) +} + +sum_dbl_foreach2_ <- function(x_sxp) { + .Call(`_cpp11test_sum_dbl_foreach2_`, x_sxp) +} + +sum_dbl_accumulate_ <- function(x) { + .Call(`_cpp11test_sum_dbl_accumulate_`, x) +} + +sum_dbl_accumulate2_ <- function(x_sxp) { + .Call(`_cpp11test_sum_dbl_accumulate2_`, x_sxp) +} + sum_int_for_ <- function(x) { .Call(`_cpp11test_sum_int_for_`, x) } @@ -195,31 +223,3 @@ rcpp_sum_dbl_accumulate_ <- function(x_sxp) { rcpp_grow_ <- function(n_sxp) { .Call(`_cpp11test_rcpp_grow_`, n_sxp) } - -sum_dbl_for_ <- function(x) { - .Call(`_cpp11test_sum_dbl_for_`, x) -} - -sum_dbl_for2_ <- function(x_sxp) { - .Call(`_cpp11test_sum_dbl_for2_`, x_sxp) -} - -sum_dbl_for3_ <- function(x_sxp) { - .Call(`_cpp11test_sum_dbl_for3_`, x_sxp) -} - -sum_dbl_foreach_ <- function(x) { - .Call(`_cpp11test_sum_dbl_foreach_`, x) -} - -sum_dbl_foreach2_ <- function(x_sxp) { - .Call(`_cpp11test_sum_dbl_foreach2_`, x_sxp) -} - -sum_dbl_accumulate_ <- function(x) { - .Call(`_cpp11test_sum_dbl_accumulate_`, x) -} - -sum_dbl_accumulate2_ <- function(x_sxp) { - .Call(`_cpp11test_sum_dbl_accumulate2_`, x_sxp) -} diff --git a/cpp11test/cpp11test.Rproj b/cpp11test/cpp11test.Rproj new file mode 100644 index 00000000..497f8bfc --- /dev/null +++ b/cpp11test/cpp11test.Rproj @@ -0,0 +1,20 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source diff --git a/cpp11test/src/cpp11.cpp b/cpp11test/src/cpp11.cpp index d38863ee..44472d85 100644 --- a/cpp11test/src/cpp11.cpp +++ b/cpp11test/src/cpp11.cpp @@ -21,54 +21,6 @@ extern "C" SEXP _cpp11test_data_frame_() { return cpp11::as_sexp(data_frame_()); END_CPP11 } -// errors_fmt.cpp -void my_stop(std::string mystring, int myarg); -extern "C" SEXP _cpp11test_my_stop(SEXP mystring, SEXP myarg) { - BEGIN_CPP11 - my_stop(cpp11::as_cpp>(mystring), cpp11::as_cpp>(myarg)); - return R_NilValue; - END_CPP11 -} -// errors_fmt.cpp -void my_stop_n1(std::string mystring); -extern "C" SEXP _cpp11test_my_stop_n1(SEXP mystring) { - BEGIN_CPP11 - my_stop_n1(cpp11::as_cpp>(mystring)); - return R_NilValue; - END_CPP11 -} -// errors_fmt.cpp -void my_warning(std::string mystring, std::string myarg); -extern "C" SEXP _cpp11test_my_warning(SEXP mystring, SEXP myarg) { - BEGIN_CPP11 - my_warning(cpp11::as_cpp>(mystring), cpp11::as_cpp>(myarg)); - return R_NilValue; - END_CPP11 -} -// errors_fmt.cpp -void my_warning_n1(std::string mystring); -extern "C" SEXP _cpp11test_my_warning_n1(SEXP mystring) { - BEGIN_CPP11 - my_warning_n1(cpp11::as_cpp>(mystring)); - return R_NilValue; - END_CPP11 -} -// errors_fmt.cpp -void my_message(std::string mystring, std::string myarg); -extern "C" SEXP _cpp11test_my_message(SEXP mystring, SEXP myarg) { - BEGIN_CPP11 - my_message(cpp11::as_cpp>(mystring), cpp11::as_cpp>(myarg)); - return R_NilValue; - END_CPP11 -} -// errors_fmt.cpp -void my_message_n1(std::string mystring); -extern "C" SEXP _cpp11test_my_message_n1(SEXP mystring) { - BEGIN_CPP11 - my_message_n1(cpp11::as_cpp>(mystring)); - return R_NilValue; - END_CPP11 -} // errors.cpp void my_stop_n1fmt(std::string mystring); extern "C" SEXP _cpp11test_my_stop_n1fmt(SEXP mystring) { @@ -117,6 +69,54 @@ extern "C" SEXP _cpp11test_my_message_n2fmt(SEXP mystring, SEXP myarg) { return R_NilValue; END_CPP11 } +// errors_fmt.cpp +void my_stop(std::string mystring, int myarg); +extern "C" SEXP _cpp11test_my_stop(SEXP mystring, SEXP myarg) { + BEGIN_CPP11 + my_stop(cpp11::as_cpp>(mystring), cpp11::as_cpp>(myarg)); + return R_NilValue; + END_CPP11 +} +// errors_fmt.cpp +void my_stop_n1(std::string mystring); +extern "C" SEXP _cpp11test_my_stop_n1(SEXP mystring) { + BEGIN_CPP11 + my_stop_n1(cpp11::as_cpp>(mystring)); + return R_NilValue; + END_CPP11 +} +// errors_fmt.cpp +void my_warning(std::string mystring, std::string myarg); +extern "C" SEXP _cpp11test_my_warning(SEXP mystring, SEXP myarg) { + BEGIN_CPP11 + my_warning(cpp11::as_cpp>(mystring), cpp11::as_cpp>(myarg)); + return R_NilValue; + END_CPP11 +} +// errors_fmt.cpp +void my_warning_n1(std::string mystring); +extern "C" SEXP _cpp11test_my_warning_n1(SEXP mystring) { + BEGIN_CPP11 + my_warning_n1(cpp11::as_cpp>(mystring)); + return R_NilValue; + END_CPP11 +} +// errors_fmt.cpp +void my_message(std::string mystring, std::string myarg); +extern "C" SEXP _cpp11test_my_message(SEXP mystring, SEXP myarg) { + BEGIN_CPP11 + my_message(cpp11::as_cpp>(mystring), cpp11::as_cpp>(myarg)); + return R_NilValue; + END_CPP11 +} +// errors_fmt.cpp +void my_message_n1(std::string mystring); +extern "C" SEXP _cpp11test_my_message_n1(SEXP mystring) { + BEGIN_CPP11 + my_message_n1(cpp11::as_cpp>(mystring)); + return R_NilValue; + END_CPP11 +} // find-intervals.cpp SEXP remove_altrep(SEXP x); extern "C" SEXP _cpp11test_remove_altrep(SEXP x) { @@ -310,6 +310,55 @@ extern "C" SEXP _cpp11test_cpp11_safe_(SEXP x_sxp) { return cpp11::as_sexp(cpp11_safe_(cpp11::as_cpp>(x_sxp))); END_CPP11 } +// sum.cpp +double sum_dbl_for_(cpp11::doubles x); +extern "C" SEXP _cpp11test_sum_dbl_for_(SEXP x) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_for_(cpp11::as_cpp>(x))); + END_CPP11 +} +// sum.cpp +double sum_dbl_for2_(SEXP x_sxp); +extern "C" SEXP _cpp11test_sum_dbl_for2_(SEXP x_sxp) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_for2_(cpp11::as_cpp>(x_sxp))); + END_CPP11 +} +// sum.cpp +double sum_dbl_for3_(SEXP x_sxp); +extern "C" SEXP _cpp11test_sum_dbl_for3_(SEXP x_sxp) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_for3_(cpp11::as_cpp>(x_sxp))); + END_CPP11 +} +// sum.cpp +double sum_dbl_foreach_(cpp11::doubles x); +extern "C" SEXP _cpp11test_sum_dbl_foreach_(SEXP x) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_foreach_(cpp11::as_cpp>(x))); + END_CPP11 +} +// sum.cpp +double sum_dbl_foreach2_(SEXP x_sxp); +extern "C" SEXP _cpp11test_sum_dbl_foreach2_(SEXP x_sxp) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_foreach2_(cpp11::as_cpp>(x_sxp))); + END_CPP11 +} +// sum.cpp +double sum_dbl_accumulate_(cpp11::doubles x); +extern "C" SEXP _cpp11test_sum_dbl_accumulate_(SEXP x) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_accumulate_(cpp11::as_cpp>(x))); + END_CPP11 +} +// sum.cpp +double sum_dbl_accumulate2_(SEXP x_sxp); +extern "C" SEXP _cpp11test_sum_dbl_accumulate2_(SEXP x_sxp) { + BEGIN_CPP11 + return cpp11::as_sexp(sum_dbl_accumulate2_(cpp11::as_cpp>(x_sxp))); + END_CPP11 +} // sum_int.cpp double sum_int_for_(cpp11::integers x); extern "C" SEXP _cpp11test_sum_int_for_(SEXP x) { @@ -373,55 +422,6 @@ extern "C" SEXP _cpp11test_rcpp_grow_(SEXP n_sxp) { return cpp11::as_sexp(rcpp_grow_(cpp11::as_cpp>(n_sxp))); END_CPP11 } -// sum.cpp -double sum_dbl_for_(cpp11::doubles x); -extern "C" SEXP _cpp11test_sum_dbl_for_(SEXP x) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_for_(cpp11::as_cpp>(x))); - END_CPP11 -} -// sum.cpp -double sum_dbl_for2_(SEXP x_sxp); -extern "C" SEXP _cpp11test_sum_dbl_for2_(SEXP x_sxp) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_for2_(cpp11::as_cpp>(x_sxp))); - END_CPP11 -} -// sum.cpp -double sum_dbl_for3_(SEXP x_sxp); -extern "C" SEXP _cpp11test_sum_dbl_for3_(SEXP x_sxp) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_for3_(cpp11::as_cpp>(x_sxp))); - END_CPP11 -} -// sum.cpp -double sum_dbl_foreach_(cpp11::doubles x); -extern "C" SEXP _cpp11test_sum_dbl_foreach_(SEXP x) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_foreach_(cpp11::as_cpp>(x))); - END_CPP11 -} -// sum.cpp -double sum_dbl_foreach2_(SEXP x_sxp); -extern "C" SEXP _cpp11test_sum_dbl_foreach2_(SEXP x_sxp) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_foreach2_(cpp11::as_cpp>(x_sxp))); - END_CPP11 -} -// sum.cpp -double sum_dbl_accumulate_(cpp11::doubles x); -extern "C" SEXP _cpp11test_sum_dbl_accumulate_(SEXP x) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_accumulate_(cpp11::as_cpp>(x))); - END_CPP11 -} -// sum.cpp -double sum_dbl_accumulate2_(SEXP x_sxp); -extern "C" SEXP _cpp11test_sum_dbl_accumulate2_(SEXP x_sxp) { - BEGIN_CPP11 - return cpp11::as_sexp(sum_dbl_accumulate2_(cpp11::as_cpp>(x_sxp))); - END_CPP11 -} extern "C" { /* .Call calls */ diff --git a/cpp11test/src/test-doubles.cpp b/cpp11test/src/test-doubles.cpp index 2d847405..95842c71 100644 --- a/cpp11test/src/test-doubles.cpp +++ b/cpp11test/src/test-doubles.cpp @@ -376,28 +376,14 @@ context("doubles-C++") { } test_that("as_doubles(integers)") { - cpp11::writable::integers y; - y.push_back(10); - y.push_back(13616); - y.push_back(124); - y.push_back(899); - cpp11::doubles i(cpp11::as_doubles(y)); - - expect_true(i[0] == 10); - expect_true(i[1] == 13616); - expect_true(i[2] == 124); - expect_true(i[3] == 899); - expect_true(TYPEOF(i) == REALSXP); - - cpp11::writable::strings e; - e.push_back("a"); - e.push_back("b"); - expect_error(cpp11::as_doubles(e)); - - cpp11::writable::integers na; - na.push_back(cpp11::na()); - cpp11::doubles na2(cpp11::as_doubles(na)); - expect_true(cpp11::is_na(na2[0])); + // cpp11::writable::integers na{NA_INTEGER}; + // cpp11::sexp na(); + + cpp11::doubles na3(cpp11::as_doubles(Rf_ScalarInteger(NA_INTEGER))); + expect_true(na3.size() == 1); + // expect_true(ISNA(na3[0])); + // expect_true(cpp11::is_na(na3[0])); + expect_true(cpp11::is_na(na3[0])); } test_that("doubles operator[] and at") { diff --git a/cpp11test/src/test-integers.cpp b/cpp11test/src/test-integers.cpp index f2e6c0f7..719f327a 100644 --- a/cpp11test/src/test-integers.cpp +++ b/cpp11test/src/test-integers.cpp @@ -39,9 +39,10 @@ context("integers-C++") { expect_true(t[3] == 100000); expect_true(TYPEOF(t) == INTSXP); - cpp11::writable::doubles na; - na.push_back(cpp11::na()); - cpp11::integers na2(cpp11::as_integers(na)); + cpp11::doubles na3(Rf_ScalarReal(NA_REAL)); + expect_true(na3.size() == 1); + + cpp11::integers na2(cpp11::as_integers(na3)); expect_true(cpp11::is_na(na2[0])); } diff --git a/inst/include/cpp11/R.hpp b/inst/include/cpp11/R.hpp index 59054591..4c2c4fa3 100644 --- a/inst/include/cpp11/R.hpp +++ b/inst/include/cpp11/R.hpp @@ -28,6 +28,7 @@ #endif // clang-format on +#include #include "cpp11/altrep.hpp" namespace cpp11 { @@ -48,8 +49,17 @@ template inline T na(); template -inline bool is_na(const T& value) { +inline typename std::enable_if::type, double>::value, + bool>::type +is_na(const T& value) { return value == na(); } +template +inline typename std::enable_if::type, double>::value, + bool>::type +is_na(const T& value) { + return ISNA(value); +} + } // namespace cpp11 diff --git a/inst/include/cpp11/doubles.hpp b/inst/include/cpp11/doubles.hpp index a20bdafa..ba537f21 100644 --- a/inst/include/cpp11/doubles.hpp +++ b/inst/include/cpp11/doubles.hpp @@ -140,11 +140,6 @@ inline double na() { return NA_REAL; } -template <> -inline bool is_na(const double& x) { - return ISNA(x); -} - // forward declarations typedef r_vector integers; @@ -154,17 +149,17 @@ int na(); template <> int r_vector::operator[](const R_xlen_t pos) const; -inline doubles as_doubles(sexp x) { +inline SEXP as_doubles(SEXP x) { if (TYPEOF(x) == REALSXP) { - return as_cpp(x); + return doubles(x); } else if (TYPEOF(x) == INTSXP) { - integers xn = as_cpp(x); + integers xn(x); R_xlen_t len = xn.size(); writable::doubles ret(len); for (R_xlen_t i = 0; i < len; ++i) { int el = xn[i]; - if (is_na(el)) { - ret[i] = na(); + if (el == NA_INTEGER) { + ret[i] = NA_REAL; } else { ret[i] = static_cast(el); } @@ -175,4 +170,5 @@ inline doubles as_doubles(sexp x) { throw type_error(REALSXP, TYPEOF(x)); } + } // namespace cpp11 diff --git a/inst/include/cpp11/integers.hpp b/inst/include/cpp11/integers.hpp index 92b1fb12..f6d80e7f 100644 --- a/inst/include/cpp11/integers.hpp +++ b/inst/include/cpp11/integers.hpp @@ -148,13 +148,10 @@ inline int na() { // forward declarations typedef r_vector doubles; -template <> -bool is_na(const double& x); - template <> double r_vector::operator[](const R_xlen_t pos) const; -inline integers as_integers(sexp x) { +inline integers as_integers(SEXP x) { if (TYPEOF(x) == INTSXP) { return as_cpp(x); } else if (TYPEOF(x) == REALSXP) { @@ -163,8 +160,8 @@ inline integers as_integers(sexp x) { writable::integers ret(len); for (R_xlen_t i = 0; i < len; ++i) { double el = xn[i]; - if (is_na(el)) { - ret[i] = na(); + if (ISNA(el)) { + ret[i] = NA_INTEGER; } else if (is_convertible_without_loss_to_integer(el)) { ret[i] = static_cast(el); } else { diff --git a/inst/include/cpp11/protect.hpp b/inst/include/cpp11/protect.hpp index acab13d6..672bf177 100644 --- a/inst/include/cpp11/protect.hpp +++ b/inst/include/cpp11/protect.hpp @@ -328,18 +328,16 @@ static struct { static SEXP list_ = get_preserve_list(); - // Get references to head, tail of the precious list. - SEXP head = list_; - SEXP tail = CDR(list_); + // Add a new cell that points to the previous end. + SEXP cell = PROTECT(Rf_cons(list_, CDR(list_))); - // Add a new cell that points to the current head + tail. - SEXP cell = PROTECT(Rf_cons(head, tail)); SET_TAG(cell, obj); - // Update the head + tail to point at the newly-created cell, - // effectively inserting that cell between the current head + tail. - SETCDR(head, cell); - SETCAR(tail, cell); + SETCDR(list_, cell); + + if (CDR(cell) != R_NilValue) { + SETCAR(CDR(cell), cell); + } UNPROTECT(2); @@ -367,25 +365,29 @@ static struct { #endif } - void release(SEXP cell) { - if (cell == R_NilValue) { + void release(SEXP token) { + if (token == R_NilValue) { return; } #ifdef CPP11_USE_PRESERVE_OBJECT - R_ReleaseObject(cell); + R_ReleaseObject(token); return; #endif - // Get a reference to the cells before and after the token. - SEXP lhs = CAR(cell); - SEXP rhs = CDR(cell); + SEXP before = CAR(token); + + SEXP after = CDR(token); + + if (before == R_NilValue && after == R_NilValue) { + Rf_error("should never happen"); + } + + SETCDR(before, after); - // Remove the cell from the precious list -- effectively, we do this - // by updating the 'lhs' and 'rhs' references to point at each-other, - // effectively removing any references to the cell in the pairlist. - SETCDR(lhs, rhs); - SETCAR(rhs, lhs); + if (after != R_NilValue) { + SETCAR(after, before); + } } private: @@ -425,24 +427,18 @@ static struct { static SEXP get_preserve_list() { static SEXP preserve_list = R_NilValue; + if (TYPEOF(preserve_list) != LISTSXP) { preserve_list = get_preserve_xptr_addr(); if (TYPEOF(preserve_list) != LISTSXP) { - preserve_list = Rf_cons(R_NilValue, Rf_cons(R_NilValue, R_NilValue)); + preserve_list = Rf_cons(R_NilValue, R_NilValue); R_PreserveObject(preserve_list); set_preserve_xptr(preserve_list); } - - // NOTE: Because older versions of cpp11 (<= 0.4.2) initialized the - // precious_list with a single cell, we might need to detect and update - // an existing empty precious list so that we have a second cell following. - if (CDR(preserve_list) == R_NilValue) - SETCDR(preserve_list, Rf_cons(R_NilValue, R_NilValue)); } return preserve_list; } - -} preserved; - +} // namespace cpp11 +preserved; } // namespace cpp11 diff --git a/inst/include/cpp11/r_vector.hpp b/inst/include/cpp11/r_vector.hpp index 4831c2f5..d0af40ef 100644 --- a/inst/include/cpp11/r_vector.hpp +++ b/inst/include/cpp11/r_vector.hpp @@ -104,6 +104,17 @@ class r_vector { preserved.release(old_protect); }; + r_vector(r_vector&& rhs) { + protect_ = rhs.protect_; + data_ = rhs.data_; + is_altrep_ = rhs.is_altrep_; + data_p_ = rhs.data_p_; + length_ = rhs.length_; + + // so that the destructor for rhs is no-op + rhs.protect_ = R_NilValue; + } + r_vector(const writable::r_vector& rhs) : r_vector(static_cast(rhs)) {} r_vector(named_arg) = delete; diff --git a/inst/include/cpp11/sexp.hpp b/inst/include/cpp11/sexp.hpp index 1517c5af..e94b11a3 100644 --- a/inst/include/cpp11/sexp.hpp +++ b/inst/include/cpp11/sexp.hpp @@ -23,17 +23,12 @@ class sexp { // REprintf("created %x %x : %i\n", data_, preserve_token_, protect_head_size()); } - sexp(const sexp& rhs) { - data_ = rhs.data_; - preserve_token_ = preserved.insert(data_); + sexp(const sexp& rhs) : data_(rhs.data_), preserve_token_(preserved.insert(rhs.data_)) { // REprintf("copied %x new protect %x : %i\n", rhs.data_, preserve_token_, // protect_head_size()); } - sexp(sexp&& rhs) { - data_ = rhs.data_; - preserve_token_ = rhs.preserve_token_; - + sexp(sexp&& rhs) : data_(rhs.data_), preserve_token_(rhs.preserve_token_) { rhs.data_ = R_NilValue; rhs.preserve_token_ = R_NilValue; @@ -41,21 +36,44 @@ class sexp { } sexp& operator=(const sexp& rhs) { - preserved.release(preserve_token_); + if (data_ != rhs.data_) { + SEXP old_preserve_token = preserve_token_; + + data_ = rhs.data_; + preserve_token_ = preserved.insert(data_); + + preserved.release(old_preserve_token); + } - data_ = rhs.data_; - preserve_token_ = preserved.insert(data_); // REprintf("assigned %x : %i\n", rhs.data_, protect_head_size()); return *this; } + sexp& operator=(sexp&& rhs) { + if (data_ != rhs.data_) { + SEXP old_preserve_token = preserve_token_; + + data_ = rhs.data_; + preserve_token_ = rhs.preserve_token_; + + rhs.data_ = R_NilValue; + rhs.preserve_token_ = R_NilValue; + preserved.release(old_preserve_token); + } + + // REprintf("moved %x : %i\n", rhs.data_, protect_head_size()); + return *this; + } + // void swap(sexp& rhs) { // sexp tmp(rhs); // rhs = *this; //*this = tmp; //} - ~sexp() { preserved.release(preserve_token_); } + ~sexp() { + preserved.release(preserve_token_); + } attribute_proxy attr(const char* name) const { return attribute_proxy(*this, name);