Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify initializer_list<T> constructors #376

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cpp11test/src/test-doubles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ context("doubles-C++") {

UNPROTECT(1);
}

test_that("writable::doubles(initializer_list<double>)") {
cpp11::writable::doubles x({1, 2.5, 3});
expect_true(x[0] == 1.0);
expect_true(x[1] == 2.5);
expect_true(x[2] == 3.0);
}

test_that("writable::doubles(SEXP, bool)") {
SEXP x = PROTECT(Rf_ScalarReal(5.));
cpp11::writable::doubles y(x, false);
Expand Down
7 changes: 7 additions & 0 deletions cpp11test/src/test-integers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ context("integers-C++") {
UNPROTECT(1);
}

test_that("writable::integers(initializer_list<int>)") {
cpp11::writable::integers x({1, 2, 3});
expect_true(x[0] == 1);
expect_true(x[1] == 2);
expect_true(x[2] == 3);
}

#if defined(__APPLE__) && defined(R_VERSION) && R_VERSION >= R_Version(3, 5, 0)
test_that("writable::integers(ALTREP_SEXP)") {
// ALTREP compact-seq
Expand Down
13 changes: 13 additions & 0 deletions cpp11test/src/test-list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,17 @@ context("list-C++") {
expect_true(Rf_xlength(y) == 0);
expect_true(y != R_NilValue);
}

test_that("writable::list(initializer_list<SEXP>)") {
SEXP x1 = PROTECT(Rf_allocVector(INTSXP, 1));
SEXP x2 = PROTECT(Rf_allocVector(REALSXP, 2));
SEXP x3 = PROTECT(Rf_allocVector(STRSXP, 3));

cpp11::writable::list x({x1, x2, x3});
expect_true(x[0] == x1);
expect_true(x[1] == x2);
expect_true(x[2] == x3);

UNPROTECT(3);
}
}
21 changes: 21 additions & 0 deletions cpp11test/src/test-logicals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,27 @@ context("logicals-C++") {

UNPROTECT(1);
}

test_that("writable::logicals(initializer_list<r_bool>)") {
cpp11::writable::logicals x(
{cpp11::r_bool(true), cpp11::r_bool(false), cpp11::r_bool(NA_INTEGER)});
expect_true(x[0] == cpp11::r_bool(true));
expect_true(x[1] == cpp11::r_bool(false));
expect_true(x[2] == cpp11::r_bool(NA_INTEGER));

// This works due to implicit conversion of `bool` to `r_bool`
cpp11::writable::logicals y({true, false, false});
expect_true(y[0] == cpp11::r_bool(true));
expect_true(y[1] == cpp11::r_bool(false));
expect_true(y[2] == cpp11::r_bool(false));

// This works due to implicit conversion of `Rboolean` to `r_bool`
cpp11::writable::logicals z({TRUE, FALSE, FALSE});
expect_true(z[0] == cpp11::r_bool(true));
expect_true(z[1] == cpp11::r_bool(false));
expect_true(z[2] == cpp11::r_bool(false));
}

test_that("is_na(r_bool)") {
cpp11::r_bool x = TRUE;
expect_true(!cpp11::is_na(x));
Expand Down
7 changes: 7 additions & 0 deletions cpp11test/src/test-raws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ context("raws-C++") {
UNPROTECT(1);
}

test_that("writable::raws(initializer_list<uint_8>)") {
cpp11::writable::raws x({1, 2, 255});
expect_true(x[0] == 1);
expect_true(x[1] == 2);
expect_true(x[2] == 255);
}

// test_that("writable::raws(ALTREP_SEXP)") {
// SEXP x = PROTECT(R_compact_uint8_trange(1, 5));
//// Need to find (or create) an altrep class that implements duplicate.
Expand Down
28 changes: 28 additions & 0 deletions cpp11test/src/test-strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,34 @@ context("strings-C++") {
UNPROTECT(1);
}

test_that("writable::strings(initializer_list<r_string>)") {
cpp11::r_string abc = cpp11::r_string("abc");
cpp11::r_string na = cpp11::r_string(NA_STRING);

cpp11::writable::strings x({abc, na, abc});
expect_true(x[0] == abc);
expect_true(x[1] == na);
expect_true(x[2] == abc);

// This works due to implicit conversion of `SEXP` to `r_string`
SEXP a = PROTECT(Rf_mkCharCE("a", CE_UTF8));
SEXP b = PROTECT(Rf_mkCharCE("b", CE_UTF8));
cpp11::writable::strings y({a, b});
expect_true(y[0] == cpp11::r_string("a"));
expect_true(y[1] == cpp11::r_string("b"));

// This works due to implicit conversion of `const char*` to `r_string`
cpp11::writable::strings z({"neat", "stuff"});
expect_true(z[0] == cpp11::r_string("neat"));
expect_true(z[1] == cpp11::r_string("stuff"));

cpp11::writable::strings w({std::string("neat"), std::string("stuff")});
expect_true(w[0] == cpp11::r_string("neat"));
expect_true(w[1] == cpp11::r_string("stuff"));

UNPROTECT(2);
}

test_that("std::initializer_list<const char*>") {
cpp11::writable::strings x{"foo"};
expect_true(x.size() == 1);
Expand Down
10 changes: 6 additions & 4 deletions inst/include/cpp11/doubles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ inline SEXPTYPE r_vector<double>::get_sexptype() {
return REALSXP;
}

template <>
inline void r_vector<double>::set_elt(
SEXP x, R_xlen_t i, typename traits::get_underlying_type<double>::type value) {
SET_REAL_ELT(x, i, value);
}

template <>
inline typename r_vector<double>::proxy& r_vector<double>::proxy::operator=(
const double& rhs) {
Expand All @@ -81,10 +87,6 @@ inline r_vector<double>::proxy::operator double() const {
}
}

template <>
inline r_vector<double>::r_vector(std::initializer_list<double> il)
: cpp11::r_vector<double>(as_sexp(il)), capacity_(il.size()) {}

template <>
inline r_vector<double>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<double>(safe[Rf_allocVector](REALSXP, il.size())),
Expand Down
10 changes: 6 additions & 4 deletions inst/include/cpp11/integers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ inline SEXPTYPE r_vector<int>::get_sexptype() {
return INTSXP;
}

template <>
inline void r_vector<int>::set_elt(
SEXP x, R_xlen_t i, typename traits::get_underlying_type<int>::type value) {
SET_INTEGER_ELT(x, i, value);
}

template <>
inline typename r_vector<int>::proxy& r_vector<int>::proxy::operator=(const int& rhs) {
if (is_altrep_) {
Expand All @@ -81,10 +87,6 @@ inline r_vector<int>::proxy::operator int() const {
}
}

template <>
inline r_vector<int>::r_vector(std::initializer_list<int> il)
: cpp11::r_vector<int>(as_sexp(il)), capacity_(il.size()) {}

template <>
inline r_vector<int>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<int>(safe[Rf_allocVector](INTSXP, il.size())),
Expand Down
16 changes: 6 additions & 10 deletions inst/include/cpp11/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ inline SEXPTYPE r_vector<SEXP>::get_sexptype() {
return VECSXP;
}

template <>
inline void r_vector<SEXP>::set_elt(
SEXP x, R_xlen_t i, typename traits::get_underlying_type<SEXP>::type value) {
SET_VECTOR_ELT(x, i, value);
}

template <>
inline typename r_vector<SEXP>::proxy& r_vector<SEXP>::proxy::operator=(const SEXP& rhs) {
SET_VECTOR_ELT(data_, index_, rhs);
Expand All @@ -79,16 +85,6 @@ inline r_vector<SEXP>::proxy::operator SEXP() const {
return VECTOR_ELT(data_, index_);
}

template <>
inline r_vector<SEXP>::r_vector(std::initializer_list<SEXP> il)
: cpp11::r_vector<SEXP>(safe[Rf_allocVector](VECSXP, il.size())),
capacity_(il.size()) {
auto it = il.begin();
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
SET_VECTOR_ELT(data_, i, *it);
}
}

template <>
inline r_vector<SEXP>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<SEXP>(safe[Rf_allocVector](VECSXP, il.size())),
Expand Down
15 changes: 6 additions & 9 deletions inst/include/cpp11/logicals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ inline SEXPTYPE r_vector<r_bool>::get_sexptype() {
return LGLSXP;
}

template <>
inline void r_vector<r_bool>::set_elt(
SEXP x, R_xlen_t i, typename traits::get_underlying_type<r_bool>::type value) {
SET_LOGICAL_ELT(x, i, value);
}

template <>
inline typename r_vector<r_bool>::proxy& r_vector<r_bool>::proxy::operator=(
const r_bool& rhs) {
Expand All @@ -82,15 +88,6 @@ inline bool operator==(const r_vector<r_bool>::proxy& lhs, r_bool rhs) {
return static_cast<r_bool>(lhs).operator==(rhs);
}

template <>
inline r_vector<r_bool>::r_vector(std::initializer_list<r_bool> il)
: cpp11::r_vector<r_bool>(Rf_allocVector(LGLSXP, il.size())), capacity_(il.size()) {
auto it = il.begin();
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
SET_LOGICAL_ELT(data_, i, *it);
}
}

template <>
inline r_vector<r_bool>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<r_bool>(safe[Rf_allocVector](LGLSXP, il.size())),
Expand Down
21 changes: 20 additions & 1 deletion inst/include/cpp11/r_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ class r_vector : public cpp11::r_vector<T> {
r_vector(const r_vector& rhs);
r_vector(r_vector&& rhs);
r_vector(const cpp11::r_vector<T>& rhs);
/// Implemented in specialization
r_vector(std::initializer_list<T> il);
/// Implemented in specialization
r_vector(std::initializer_list<named_arg> il);
Expand Down Expand Up @@ -308,6 +307,8 @@ class r_vector : public cpp11::r_vector<T> {
private:
/// Implemented in specialization
static SEXPTYPE get_sexptype();
/// Implemented in specialization
static void set_elt(SEXP x, R_xlen_t i, underlying_type value);

using cpp11::r_vector<T>::get_p;
};
Expand Down Expand Up @@ -717,6 +718,24 @@ template <typename T>
inline r_vector<T>::r_vector(const cpp11::r_vector<T>& rhs)
: cpp11::r_vector<T>(safe[Rf_shallow_duplicate](rhs.data_)), capacity_(rhs.length_) {}

template <typename T>
inline r_vector<T>::r_vector(std::initializer_list<T> il)
: cpp11::r_vector<T>(safe[Rf_allocVector](get_sexptype(), il.size())),
capacity_(il.size()) {
auto it = il.begin();

if (data_p_ != nullptr) {
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
data_p_[i] = static_cast<underlying_type>(*it);
}
} else {
// Handles both the ALTREP and VECSXP cases
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
set_elt(data_, i, static_cast<underlying_type>(*it));
}
}
}

template <typename T>
inline r_vector<T>::r_vector(const R_xlen_t size) : r_vector() {
resize(size);
Expand Down
21 changes: 11 additions & 10 deletions inst/include/cpp11/raws.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <cstdint> // for uint8_t
#include <initializer_list> // for initializer_list

#include "Rversion.h"
#include "cpp11/R.hpp" // for RAW, SEXP, SEXPREC, Rf_allocVector
#include "cpp11/attribute_proxy.hpp" // for attribute_proxy
#include "cpp11/named_arg.hpp" // for named_arg
Expand Down Expand Up @@ -67,6 +68,16 @@ inline SEXPTYPE r_vector<uint8_t>::get_sexptype() {
return RAWSXP;
}

template <>
inline void r_vector<uint8_t>::set_elt(
SEXP x, R_xlen_t i, typename traits::get_underlying_type<uint8_t>::type value) {
#if R_VERSION >= R_Version(4, 2, 0)
SET_RAW_ELT(x, i, value);
#else
RAW(x)[i] = value;
#endif
}

template <>
inline typename r_vector<uint8_t>::proxy& r_vector<uint8_t>::proxy::operator=(
const uint8_t& rhs) {
Expand All @@ -89,16 +100,6 @@ inline r_vector<uint8_t>::proxy::operator uint8_t() const {
}
}

template <>
inline r_vector<uint8_t>::r_vector(std::initializer_list<uint8_t> il)
: cpp11::r_vector<uint8_t>(safe[Rf_allocVector](RAWSXP, il.size())),
capacity_(il.size()) {
auto it = il.begin();
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
data_p_[i] = *it;
}
}

template <>
inline r_vector<uint8_t>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<uint8_t>(safe[Rf_allocVector](RAWSXP, il.size())),
Expand Down
25 changes: 24 additions & 1 deletion inst/include/cpp11/strings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ inline SEXPTYPE r_vector<r_string>::get_sexptype() {
return STRSXP;
}

template <>
inline void r_vector<r_string>::set_elt(
SEXP x, R_xlen_t i, typename traits::get_underlying_type<r_string>::type value) {
SET_STRING_ELT(x, i, value);
}

template <>
inline typename r_vector<r_string>::proxy& r_vector<r_string>::proxy::operator=(
const r_string& rhs) {
Expand Down Expand Up @@ -113,9 +119,26 @@ inline r_vector<r_string>::r_vector(SEXP&& data)
}
}

// Requires specialization to handle `NA_STRING` and UTF-8 translation
template <>
inline r_vector<r_string>::r_vector(std::initializer_list<r_string> il)
: cpp11::r_vector<r_string>(as_sexp(il)), capacity_(il.size()) {}
: cpp11::r_vector<r_string>(safe[Rf_allocVector](STRSXP, il.size())),
capacity_(il.size()) {
unwind_protect([&] {
auto it = il.begin();

for (R_xlen_t i = 0; i < capacity_; ++i, ++it) {
// i.e. to `SEXP`
underlying_type elt = static_cast<underlying_type>(*it);

if (elt == NA_STRING) {
set_elt(data_, i, elt);
} else {
set_elt(data_, i, Rf_mkCharCE(Rf_translateCharUTF8(elt), CE_UTF8));
}
}
});
}

template <>
inline r_vector<r_string>::r_vector(std::initializer_list<named_arg> il)
Expand Down
Loading