Add all std::iterator_traits required types to const_iterator of rust::Vec<T> (#157)

https://en.cppreference.com/w/cpp/iterator/iterator_traits

`std::iterator_traits` requires the following 5 types:

- `difference_type` - a signed integer type that can be used to identify distance between iterators
- `value_type` - the type of the values that can be obtained by dereferencing the iterator. This type is void for output iterators.
- `pointer` - defines a pointer to the type iterated over (value_type)
- `reference` - defines a reference to the type iterated over (value_type)
- `iterator_category` - the category of the iterator. Must be one of iterator category tags.

The current `const_iterator` for `rust::Vec<T>` only defined `value_type` and `reference` which caused an error when using `std::copy` on gcc 7.5.0 on Ubuntu but seemed to work fine on MacOS.
This commit is contained in:
myronahn 2020-04-29 05:47:23 +07:00 committed by GitHub
parent 776fd8953d
commit da9be50ad8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 4 deletions

View File

@ -235,15 +235,25 @@ public:
class const_iterator {
public:
using difference_type = ptrdiff_t;
using value_type = typename std::add_const<T>::type;
using pointer = typename std::add_pointer<
typename std::add_const<T>::type>::type;
using reference = typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type;
using iterator_category = std::forward_iterator_tag;
const T &operator*() const { return *static_cast<const T *>(this->pos); }
const T *operator->() const { return static_cast<const T *>(this->pos); }
const_iterator &operator++() {
this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
return *this;
}
const_iterator operator++(int) {
auto ret = const_iterator(*this);
this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
return ret;
}
bool operator==(const const_iterator &other) const {
return this->pos == other.pos;
}

View File

@ -53,7 +53,9 @@ pub mod ffi {
fn c_take_ref_vector(v: &CxxVector<u8>);
fn c_take_rust_vec(v: Vec<u8>);
fn c_take_rust_vec_shared(v: Vec<Shared>);
fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
fn c_take_ref_rust_vec(v: &Vec<u8>);
fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
fn c_take_callback(callback: fn(String) -> usize);
fn c_try_return_void() -> Result<()>;

View File

@ -203,6 +203,18 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
}
}
void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
// Exercise requirements of ForwardIterator
// https://en.cppreference.com/w/cpp/named_req/ForwardIterator
uint32_t sum = 0;
for (auto it = v.begin(), it_end = v.end(); it != it_end; it++) {
sum += it->z;
}
if (sum == 2021) {
cxx_test_suite_set_correct();
}
}
void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
if (sum == 200) {
@ -210,6 +222,18 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
}
}
void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
// The std::copy() will make sure rust::Vec<>::const_iterator satisfies the
// requirements for std::iterator_traits.
// https://en.cppreference.com/w/cpp/iterator/iterator_traits
std::vector<uint8_t> cxx_v;
std::copy(v.begin(), v.end(), back_inserter(cxx_v));
uint8_t sum = std::accumulate(cxx_v.begin(), cxx_v.end(), 0);
if (sum == 200) {
cxx_test_suite_set_correct();
}
}
void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
callback("2020");
}

View File

@ -57,7 +57,9 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
void c_take_ref_vector(const std::vector<uint8_t> &v);
void c_take_rust_vec(rust::Vec<uint8_t> v);
void c_take_rust_vec_shared(rust::Vec<Shared> v);
void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
void c_take_callback(rust::Fn<size_t(rust::String)> callback);
void c_try_return_void();

View File

@ -94,14 +94,18 @@ fn test_c_take() {
ffi::c_return_unique_ptr_vector_shared()
));
check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
check!(ffi::c_take_rust_vec([86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec();
check!(ffi::c_take_rust_vec(test_vec.clone()));
check!(ffi::c_take_rust_vec_shared(vec![
ffi::Shared { z: 1010 },
ffi::Shared { z: 1011 }
]));
check!(ffi::c_take_ref_rust_vec(
&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()
));
check!(ffi::c_take_rust_vec_shared_forward_iterator(vec![
ffi::Shared { z: 1010 },
ffi::Shared { z: 1011 }
]));
check!(ffi::c_take_ref_rust_vec(&test_vec));
check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
}
#[test]