You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4d1aee2
Browse filesBrowse the repository at this point in the historyBrowse files
Closes#539.
A rule for a container iterator such as `std::vector<T, A>::iterator`
cannot match a usage, because `T` and `A` cannot be deduced from the
iterator type (see #539).
This PR matches iterator types by their [iterator
category](https://en.cppreference.com/w/cpp/iterator) instead. The
category is read from `std::iterator_traits<It>`, which every standard
iterator provides, so the rules do not depend on how a particular
standard library implements its iterators.
This also removes duplicate rules. One rule for random access iterators
replaces one rule per container that has a random access iterator.
---
- `rules/iterator_category/shim.rs` defines the Rust types for the
iterator categories used in translated code: iterator, input, output,
bidirectional, and random ac
cess.
- `rules/iterator_category/src.cpp` defines a type rule for each
category plus rules for its operations.
For example, this is the rule for an iterator that is bidirectional but
not random access:
```cpp
template <
typename It, typename T1 = typename std::iterator_traits<It>::value_type,
typename = typename std::enable_if<
std::is_base_of<
std::bidirectional_iterator_tag,
typename std::iterator_traits<It>::iterator_category>::value &&
!std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<It>::iterator_category>::value &&
!std::is_pointer<It>::value>::type>
using t4 = It;
```
`It` is deduced directly from the usage, and `T1` and the `enable_if`
condition are computed from it using only standard names. This rule
matches `std::map<K, V>::iterator`, `std::set<T>::iterator`,
`std::list<T>::iterator`, and so on, without naming any of them.
---
The existing vector and map iterator rules are rewritten in terms of
`RandomAccessIterator` and `BidirectionalIterator`.
- vector: `RandomAccessIterator<T>` is a `Ptr<T>`, which is what vector
iterators already translated to, so the change is small.
- map: `RefcountMapIter` and `UnsafeMapIterator` were `MapIter<K,
MapRef>`, which has two type parameters. A category rule only knows `T`,
the iterator's `value_type`, which for a map is `std::pair<const K, V>`.
The Rust iterator type therefore has to depend on `T` alone. The new map
iterator is built on `MapNode<T>`. The map itself still owns a
`BTreeMap`.
The converter special cases for map iterators
(`GetStrongestIteratorCategory`, `PushSuppressIteratorClone`, and the
`Vec<`/`BTreeMap<` checks in `RecordHasCopyableFields`) are removed,
since the rules now handle these types.
---
Function rules that take the container as an argument already work, even
when they also spell a container member type. For example
`std::map::erase`:
```cpp
template <typename T1, typename T2>
typename std::map<T1, T2>::iterator
f27(std::map<T1, T2> &o, typename std::map<T1, T2>::const_iterator it) {
return o.erase(it);
}
template <typename T1, typename T2>
std::size_t f28(std::map<T1, T2> &o,
const typename std::map<T1, T2>::key_type &key) {
return o.erase(key);
}
```
`std::map<T1, T2>::const_iterator` is still a non-deduced context, but
that does not matter here: `T1` and `T2` are deduced from the first
parameter `o`, and Clang then substitutes them into the second
parameter. Deduction only fails when the iterator is the only place the
template parameters appear, as in the type rule `using t = typename
std::map<T1, T2>::iterator;`. Those are the rules this PR replaces.
0 commit comments