Skip to content

Commit 364e713

Browse files
authored
Add get_elt() to unify more specialization methods (#380)
* Add `get_elt()` helper * Move `[]` element access operator to `r_vector.hpp` * Implement `proxy::operator T()` in `r_vector.hpp`
1 parent dccd4f6 commit 364e713

File tree

7 files changed

+58
-87
lines changed

7 files changed

+58
-87
lines changed

inst/include/cpp11/doubles.hpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616

1717
namespace cpp11 {
1818

19+
template <>
20+
inline typename r_vector<double>::underlying_type r_vector<double>::get_elt(SEXP x,
21+
R_xlen_t i) {
22+
// NOPROTECT: likely too costly to unwind protect every elt
23+
return REAL_ELT(x, i);
24+
}
25+
1926
template <>
2027
inline SEXP r_vector<double>::valid_type(SEXP data) {
2128
if (data == nullptr) {
@@ -27,12 +34,6 @@ inline SEXP r_vector<double>::valid_type(SEXP data) {
2734
return data;
2835
}
2936

30-
template <>
31-
inline double r_vector<double>::operator[](const R_xlen_t pos) const {
32-
// NOPROTECT: likely too costly to unwind protect every elt
33-
return is_altrep_ ? REAL_ELT(data_, pos) : data_p_[pos];
34-
}
35-
3637
template <>
3738
inline typename r_vector<double>::underlying_type* r_vector<double>::get_p(bool is_altrep,
3839
SEXP data) {
@@ -70,16 +71,6 @@ inline void r_vector<double>::set_elt(SEXP x, R_xlen_t i,
7071
SET_REAL_ELT(x, i, value);
7172
}
7273

73-
template <>
74-
inline r_vector<double>::proxy::operator double() const {
75-
if (p_ == nullptr) {
76-
// NOPROTECT: likely too costly to unwind protect every elt
77-
return REAL_ELT(data_, index_);
78-
} else {
79-
return *p_;
80-
}
81-
}
82-
8374
template <>
8475
inline r_vector<double>::r_vector(std::initializer_list<named_arg> il)
8576
: cpp11::r_vector<double>(safe[Rf_allocVector](REALSXP, il.size())),

inst/include/cpp11/integers.hpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717

1818
namespace cpp11 {
1919

20+
template <>
21+
inline typename r_vector<int>::underlying_type r_vector<int>::get_elt(SEXP x,
22+
R_xlen_t i) {
23+
// NOPROTECT: likely too costly to unwind protect every elt
24+
return INTEGER_ELT(x, i);
25+
}
26+
2027
template <>
2128
inline SEXP r_vector<int>::valid_type(SEXP data) {
2229
if (data == nullptr) {
@@ -28,12 +35,6 @@ inline SEXP r_vector<int>::valid_type(SEXP data) {
2835
return data;
2936
}
3037

31-
template <>
32-
inline int r_vector<int>::operator[](const R_xlen_t pos) const {
33-
// NOPROTECT: likely too costly to unwind protect every elt
34-
return is_altrep_ ? INTEGER_ELT(data_, pos) : data_p_[pos];
35-
}
36-
3738
template <>
3839
inline typename r_vector<int>::underlying_type* r_vector<int>::get_p(bool is_altrep,
3940
SEXP data) {
@@ -71,16 +72,6 @@ inline void r_vector<int>::set_elt(SEXP x, R_xlen_t i,
7172
SET_INTEGER_ELT(x, i, value);
7273
}
7374

74-
template <>
75-
inline r_vector<int>::proxy::operator int() const {
76-
if (p_ == nullptr) {
77-
// NOPROTECT: likely too costly to unwind protect every elt
78-
return INTEGER_ELT(data_, index_);
79-
} else {
80-
return *p_;
81-
}
82-
}
83-
8475
template <>
8576
inline r_vector<int>::r_vector(std::initializer_list<named_arg> il)
8677
: cpp11::r_vector<int>(safe[Rf_allocVector](INTSXP, il.size())),

inst/include/cpp11/list.hpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414

1515
namespace cpp11 {
1616

17+
template <>
18+
inline typename r_vector<SEXP>::underlying_type r_vector<SEXP>::get_elt(SEXP x,
19+
R_xlen_t i) {
20+
// NOPROTECT: likely too costly to unwind protect every elt
21+
return VECTOR_ELT(x, i);
22+
}
23+
1724
template <>
1825
inline SEXP r_vector<SEXP>::valid_type(SEXP data) {
1926
if (data == nullptr) {
@@ -25,11 +32,6 @@ inline SEXP r_vector<SEXP>::valid_type(SEXP data) {
2532
return data;
2633
}
2734

28-
template <>
29-
inline SEXP r_vector<SEXP>::operator[](const R_xlen_t pos) const {
30-
return VECTOR_ELT(data_, pos);
31-
}
32-
3335
template <>
3436
inline SEXP r_vector<SEXP>::operator[](const r_string& name) const {
3537
SEXP names = this->names();
@@ -80,11 +82,6 @@ inline void r_vector<SEXP>::set_elt(SEXP x, R_xlen_t i,
8082
SET_VECTOR_ELT(x, i, value);
8183
}
8284

83-
template <>
84-
inline r_vector<SEXP>::proxy::operator SEXP() const {
85-
return VECTOR_ELT(data_, index_);
86-
}
87-
8885
template <>
8986
inline r_vector<SEXP>::r_vector(std::initializer_list<named_arg> il)
9087
: cpp11::r_vector<SEXP>(safe[Rf_allocVector](VECSXP, il.size())),

inst/include/cpp11/logicals.hpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616

1717
namespace cpp11 {
1818

19+
template <>
20+
inline typename r_vector<r_bool>::underlying_type r_vector<r_bool>::get_elt(SEXP x,
21+
R_xlen_t i) {
22+
// NOPROTECT: likely too costly to unwind protect every elt
23+
return LOGICAL_ELT(x, i);
24+
}
25+
1926
template <>
2027
inline SEXP r_vector<r_bool>::valid_type(SEXP data) {
2128
if (data == nullptr) {
@@ -27,11 +34,6 @@ inline SEXP r_vector<r_bool>::valid_type(SEXP data) {
2734
return data;
2835
}
2936

30-
template <>
31-
inline r_bool r_vector<r_bool>::operator[](const R_xlen_t pos) const {
32-
return is_altrep_ ? LOGICAL_ELT(data_, pos) : data_p_[pos];
33-
}
34-
3537
template <>
3638
inline typename r_vector<r_bool>::underlying_type* r_vector<r_bool>::get_p(bool is_altrep,
3739
SEXP data) {
@@ -80,15 +82,6 @@ inline typename r_vector<r_bool>::proxy& r_vector<r_bool>::proxy::operator=(
8082
return *this;
8183
}
8284

83-
template <>
84-
inline r_vector<r_bool>::proxy::operator r_bool() const {
85-
if (p_ == nullptr) {
86-
return LOGICAL_ELT(data_, index_);
87-
} else {
88-
return *p_;
89-
}
90-
}
91-
9285
inline bool operator==(const r_vector<r_bool>::proxy& lhs, r_bool rhs) {
9386
return static_cast<r_bool>(lhs).operator==(rhs);
9487
}

inst/include/cpp11/r_vector.hpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ class r_vector {
7272
#ifdef LONG_VECTOR_SUPPORT
7373
T operator[](const int pos) const;
7474
#endif
75-
/// Implemented by specialization
7675
T operator[](const R_xlen_t pos) const;
7776
T operator[](const size_type pos) const;
7877
T operator[](const r_string& name) const;
@@ -143,6 +142,8 @@ class r_vector {
143142
};
144143

145144
private:
145+
/// Implemented in specialization
146+
static underlying_type get_elt(SEXP x, R_xlen_t i);
146147
/// Implemented in specialization
147148
static underlying_type* get_p(bool is_altrep, SEXP data);
148149
/// Implemented in specialization
@@ -262,7 +263,6 @@ class r_vector : public cpp11::r_vector<T> {
262263
public:
263264
proxy(SEXP data, const R_xlen_t index, underlying_type* const p, bool is_altrep);
264265

265-
/// Implemented in specialization
266266
proxy& operator=(const T& rhs);
267267
proxy& operator+=(const T& rhs);
268268
proxy& operator-=(const T& rhs);
@@ -274,7 +274,6 @@ class r_vector : public cpp11::r_vector<T> {
274274
void operator++();
275275
void operator--();
276276

277-
/// Implemented in specialization
278277
operator T() const;
279278
};
280279

@@ -445,6 +444,13 @@ inline T r_vector<T>::operator[](const int pos) const {
445444
}
446445
#endif
447446

447+
template <typename T>
448+
inline T r_vector<T>::operator[](const R_xlen_t pos) const {
449+
// Handles ALTREP, VECSXP, and STRSXP cases through `get_elt()`
450+
const underlying_type elt = (data_p_ != nullptr) ? data_p_[pos] : get_elt(data_, pos);
451+
return static_cast<T>(elt);
452+
}
453+
448454
template <typename T>
449455
inline T r_vector<T>::operator[](const size_type pos) const {
450456
return operator[](static_cast<R_xlen_t>(pos));
@@ -1082,6 +1088,13 @@ inline void r_vector<T>::proxy::operator--() {
10821088
operator=(static_cast<T>(*this) - 1);
10831089
}
10841090

1091+
template <typename T>
1092+
inline r_vector<T>::proxy::operator T() const {
1093+
// Handles ALTREP, VECSXP, and STRSXP cases through `get_elt()`
1094+
const underlying_type elt = (p_ != nullptr) ? *p_ : r_vector::get_elt(data_, index_);
1095+
return static_cast<T>(elt);
1096+
}
1097+
10851098
template <typename T>
10861099
r_vector<T>::iterator::iterator(const r_vector& data, R_xlen_t pos)
10871100
: r_vector::const_iterator(&data, pos), data_(data) {}

inst/include/cpp11/raws.hpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ struct get_underlying_type<uint8_t> {
2424
};
2525
} // namespace traits
2626

27+
template <>
28+
inline typename r_vector<uint8_t>::underlying_type r_vector<uint8_t>::get_elt(
29+
SEXP x, R_xlen_t i) {
30+
// NOPROTECT: likely too costly to unwind protect every elt
31+
return RAW_ELT(x, i);
32+
}
33+
2734
template <>
2835
inline SEXP r_vector<uint8_t>::valid_type(SEXP data) {
2936
if (data == nullptr) {
@@ -35,12 +42,6 @@ inline SEXP r_vector<uint8_t>::valid_type(SEXP data) {
3542
return data;
3643
}
3744

38-
template <>
39-
inline uint8_t r_vector<uint8_t>::operator[](const R_xlen_t pos) const {
40-
// NOPROTECT: likely too costly to unwind protect every elt
41-
return is_altrep_ ? RAW_ELT(data_, pos) : data_p_[pos];
42-
}
43-
4445
template <>
4546
inline typename r_vector<uint8_t>::underlying_type* r_vector<uint8_t>::get_p(
4647
bool is_altrep, SEXP data) {
@@ -82,16 +83,6 @@ inline void r_vector<uint8_t>::set_elt(SEXP x, R_xlen_t i,
8283
#endif
8384
}
8485

85-
template <>
86-
inline r_vector<uint8_t>::proxy::operator uint8_t() const {
87-
if (p_ == nullptr) {
88-
// NOPROTECT: likely too costly to unwind protect every elt
89-
return RAW(data_)[index_];
90-
} else {
91-
return *p_;
92-
}
93-
}
94-
9586
template <>
9687
inline r_vector<uint8_t>::r_vector(std::initializer_list<named_arg> il)
9788
: cpp11::r_vector<uint8_t>(safe[Rf_allocVector](RAWSXP, il.size())),

inst/include/cpp11/strings.hpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616

1717
namespace cpp11 {
1818

19+
template <>
20+
inline typename r_vector<r_string>::underlying_type r_vector<r_string>::get_elt(
21+
SEXP x, R_xlen_t i) {
22+
// NOPROTECT: likely too costly to unwind protect every elt
23+
return STRING_ELT(x, i);
24+
}
25+
1926
template <>
2027
inline SEXP r_vector<r_string>::valid_type(SEXP data) {
2128
if (data == nullptr) {
@@ -27,12 +34,6 @@ inline SEXP r_vector<r_string>::valid_type(SEXP data) {
2734
return data;
2835
}
2936

30-
template <>
31-
inline r_string r_vector<r_string>::operator[](const R_xlen_t pos) const {
32-
// NOPROTECT: likely too costly to unwind protect every elt
33-
return STRING_ELT(data_, pos);
34-
}
35-
3637
template <>
3738
inline typename r_vector<r_string>::underlying_type* r_vector<r_string>::get_p(bool,
3839
SEXP) {
@@ -70,12 +71,6 @@ inline void r_vector<r_string>::set_elt(SEXP x, R_xlen_t i,
7071
SET_STRING_ELT(x, i, value);
7172
}
7273

73-
template <>
74-
inline r_vector<r_string>::proxy::operator r_string() const {
75-
// NOPROTECT: likely too costly to unwind protect every elt
76-
return STRING_ELT(data_, index_);
77-
}
78-
7974
inline bool operator==(const r_vector<r_string>::proxy& lhs, r_string rhs) {
8075
return static_cast<r_string>(lhs).operator==(static_cast<std::string>(rhs).c_str());
8176
}

0 commit comments

Comments
 (0)