-
Notifications
You must be signed in to change notification settings - Fork 51
Ensure that data_p_
is typed with the underlying type of data_
#267
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,22 +29,23 @@ inline SEXP r_vector<r_bool>::valid_type(SEXP data) { | |
|
||
template <> | ||
inline r_bool r_vector<r_bool>::operator[](const R_xlen_t pos) const { | ||
return is_altrep_ ? static_cast<r_bool>(LOGICAL_ELT(data_, pos)) : data_p_[pos]; | ||
return is_altrep_ ? LOGICAL_ELT(data_, pos) : data_p_[pos]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I am not sure what best practice is here, rely on implicit casts to the return value, or be explicit with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently it is a Core Guideline to avoid implicit conversions where possible http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c164-avoid-implicit-conversion-operators I resonate strongly with this! However, I will leave this as is for now since we use implicit casts in many cases already. It would be even more apparent that we should be using an explicit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that explicit is better. |
||
} | ||
|
||
template <> | ||
inline r_bool* r_vector<r_bool>::get_p(bool is_altrep, SEXP data) { | ||
inline typename r_vector<r_bool>::underlying_type* r_vector<r_bool>::get_p(bool is_altrep, | ||
SEXP data) { | ||
if (is_altrep) { | ||
return nullptr; | ||
} else { | ||
return reinterpret_cast<r_bool*>(LOGICAL(data)); | ||
return LOGICAL(data); | ||
Comment on lines
-40
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was the motivating example. |
||
} | ||
} | ||
|
||
template <> | ||
inline void r_vector<r_bool>::const_iterator::fill_buf(R_xlen_t pos) { | ||
length_ = std::min(64_xl, data_->size() - pos); | ||
LOGICAL_GET_REGION(data_->data_, pos, length_, reinterpret_cast<int*>(buf_.data())); | ||
LOGICAL_GET_REGION(data_->data_, pos, length_, buf_.data()); | ||
Comment on lines
-47
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
block_start_ = pos; | ||
} | ||
|
||
|
@@ -66,7 +67,7 @@ inline typename r_vector<r_bool>::proxy& r_vector<r_bool>::proxy::operator=( | |
template <> | ||
inline r_vector<r_bool>::proxy::operator r_bool() const { | ||
if (p_ == nullptr) { | ||
return static_cast<r_bool>(LOGICAL_ELT(data_, index_)); | ||
return LOGICAL_ELT(data_, index_); | ||
} else { | ||
return *p_; | ||
} | ||
|
@@ -100,7 +101,7 @@ inline r_vector<r_bool>::r_vector(std::initializer_list<named_arg> il) | |
++n_protected; | ||
auto it = il.begin(); | ||
for (R_xlen_t i = 0; i < capacity_; ++i, ++it) { | ||
data_p_[i] = static_cast<r_bool>(LOGICAL_ELT(it->value(), 0)); | ||
data_p_[i] = LOGICAL_ELT(it->value(), 0); | ||
SET_STRING_ELT(names, i, Rf_mkCharCE(it->name(), CE_UTF8)); | ||
} | ||
UNPROTECT(n_protected); | ||
|
@@ -121,7 +122,7 @@ inline void r_vector<r_bool>::reserve(R_xlen_t new_capacity) { | |
|
||
preserved.release(old_protect); | ||
|
||
data_p_ = reinterpret_cast<r_bool*>(LOGICAL(data_)); | ||
data_p_ = LOGICAL(data_); | ||
capacity_ = new_capacity; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,8 @@ class r_vector { | |
typedef T* pointer; | ||
typedef T& reference; | ||
|
||
using underlying_type = typename traits::get_underlying_type<T>::type; | ||
|
||
r_vector() noexcept = default; | ||
|
||
r_vector(SEXP data); | ||
|
@@ -173,7 +175,7 @@ class r_vector { | |
void fill_buf(R_xlen_t pos); | ||
|
||
R_xlen_t pos_; | ||
std::array<T, 64 * 64> buf_; | ||
std::array<underlying_type, 64 * 64> buf_; | ||
R_xlen_t block_start_ = 0; | ||
R_xlen_t length_ = 0; | ||
}; | ||
|
@@ -193,10 +195,10 @@ class r_vector { | |
SEXP data_ = R_NilValue; | ||
SEXP protect_ = R_NilValue; | ||
bool is_altrep_ = false; | ||
T* data_p_ = nullptr; | ||
underlying_type* data_p_ = nullptr; | ||
R_xlen_t length_ = 0; | ||
|
||
static T* get_p(bool is_altrep, SEXP data); | ||
static underlying_type* get_p(bool is_altrep, SEXP data); | ||
|
||
static SEXP valid_type(SEXP data); | ||
|
||
|
@@ -216,6 +218,8 @@ class r_vector : public cpp11::r_vector<T> { | |
|
||
// These are necessary because type names are not directly accessible in | ||
// template inheritance | ||
using typename cpp11::r_vector<T>::underlying_type; | ||
|
||
using cpp11::r_vector<T>::data_; | ||
using cpp11::r_vector<T>::data_p_; | ||
using cpp11::r_vector<T>::is_altrep_; | ||
|
@@ -228,11 +232,11 @@ class r_vector : public cpp11::r_vector<T> { | |
private: | ||
const SEXP data_; | ||
const R_xlen_t index_; | ||
T* const p_; | ||
underlying_type* const p_; | ||
bool is_altrep_; | ||
|
||
public: | ||
proxy(SEXP data, const R_xlen_t index, T* const p, bool is_altrep); | ||
proxy(SEXP data, const R_xlen_t index, underlying_type* const p, bool is_altrep); | ||
|
||
proxy& operator=(const T& rhs); | ||
proxy& operator+=(const T& rhs); | ||
|
@@ -572,9 +576,9 @@ inline typename cpp11::r_vector<T>::const_iterator cpp11::r_vector<T>::find( | |
template <typename T> | ||
inline T r_vector<T>::const_iterator::operator*() const { | ||
if (data_->is_altrep()) { | ||
return buf_[pos_ - block_start_]; | ||
return static_cast<T>(buf_[pos_ - block_start_]); | ||
} else { | ||
return data_->data_p_[pos_]; | ||
return static_cast<T>(data_->data_p_[pos_]); | ||
Comment on lines
-575
to
+581
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably don't need these, the implicit casts to |
||
} | ||
} | ||
|
||
|
@@ -598,13 +602,17 @@ inline T r_vector<T>::operator[](size_type pos) const { | |
namespace writable { | ||
|
||
template <typename T> | ||
r_vector<T>::proxy::proxy(SEXP data, const R_xlen_t index, T* const p, bool is_altrep) | ||
r_vector<T>::proxy::proxy(SEXP data, const R_xlen_t index, | ||
typename r_vector<T>::underlying_type* const p, bool is_altrep) | ||
: data_(data), index_(index), p_(p), is_altrep_(is_altrep) {} | ||
|
||
template <typename T> | ||
inline typename r_vector<T>::proxy r_vector<T>::iterator::operator*() const { | ||
if (data_.is_altrep()) { | ||
return proxy(data_.data(), pos_, const_cast<T*>(&buf_[pos_ - block_start_]), true); | ||
return proxy( | ||
data_.data(), pos_, | ||
const_cast<typename r_vector<T>::underlying_type*>(&buf_[pos_ - block_start_]), | ||
true); | ||
} else { | ||
return proxy(data_.data(), pos_, | ||
data_.data_p_ != nullptr ? &data_.data_p_[pos_] : nullptr, false); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
traits
namespace may be overkill, I'm not sure.I have seen this idea used elsewhere though. One of those places is Rcpp:
https://github.com/RcppCore/Rcpp/blob/master/inst/include/Rcpp/traits/storage_type.h