Commit c8360593 by Sergei Izmailov Committed by GitHub

feature: Support move-only iterators in `py::make_*iterator` (#4834)

* feature: Support move-only iterators in `py::make_*iterator`

* fix: Missing static assertion message

* fixup: Missing `explicit` in single argument constructors

* fix: Simplify tests: make existing iterator move-only

* fix: Missing `noexcept`
parent 4a2f7e46
...@@ -2434,7 +2434,7 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&...extra) { ...@@ -2434,7 +2434,7 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&...extra) {
Policy); Policy);
} }
return cast(state{first, last, true}); return cast(state{std::forward<Iterator>(first), std::forward<Sentinel>(last), true});
} }
PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(detail)
...@@ -2451,7 +2451,9 @@ iterator make_iterator(Iterator first, Sentinel last, Extra &&...extra) { ...@@ -2451,7 +2451,9 @@ iterator make_iterator(Iterator first, Sentinel last, Extra &&...extra) {
Iterator, Iterator,
Sentinel, Sentinel,
ValueType, ValueType,
Extra...>(first, last, std::forward<Extra>(extra)...); Extra...>(std::forward<Iterator>(first),
std::forward<Sentinel>(last),
std::forward<Extra>(extra)...);
} }
/// Makes a python iterator over the keys (`.first`) of a iterator over pairs from a /// Makes a python iterator over the keys (`.first`) of a iterator over pairs from a
...@@ -2467,7 +2469,9 @@ iterator make_key_iterator(Iterator first, Sentinel last, Extra &&...extra) { ...@@ -2467,7 +2469,9 @@ iterator make_key_iterator(Iterator first, Sentinel last, Extra &&...extra) {
Iterator, Iterator,
Sentinel, Sentinel,
KeyType, KeyType,
Extra...>(first, last, std::forward<Extra>(extra)...); Extra...>(std::forward<Iterator>(first),
std::forward<Sentinel>(last),
std::forward<Extra>(extra)...);
} }
/// Makes a python iterator over the values (`.second`) of a iterator over pairs from a /// Makes a python iterator over the values (`.second`) of a iterator over pairs from a
...@@ -2483,7 +2487,9 @@ iterator make_value_iterator(Iterator first, Sentinel last, Extra &&...extra) { ...@@ -2483,7 +2487,9 @@ iterator make_value_iterator(Iterator first, Sentinel last, Extra &&...extra) {
Iterator, Iterator,
Sentinel, Sentinel,
ValueType, ValueType,
Extra...>(first, last, std::forward<Extra>(extra)...); Extra...>(std::forward<Iterator>(first),
std::forward<Sentinel>(last),
std::forward<Extra>(extra)...);
} }
/// Makes an iterator over values of an stl container or other container supporting /// Makes an iterator over values of an stl container or other container supporting
......
...@@ -28,6 +28,13 @@ class NonZeroIterator { ...@@ -28,6 +28,13 @@ class NonZeroIterator {
public: public:
explicit NonZeroIterator(const T *ptr) : ptr_(ptr) {} explicit NonZeroIterator(const T *ptr) : ptr_(ptr) {}
// Make the iterator non-copyable and movable
NonZeroIterator(const NonZeroIterator &) = delete;
NonZeroIterator(NonZeroIterator &&) noexcept = default;
NonZeroIterator &operator=(const NonZeroIterator &) = delete;
NonZeroIterator &operator=(NonZeroIterator &&) noexcept = default;
const T &operator*() const { return *ptr_; } const T &operator*() const { return *ptr_; }
NonZeroIterator &operator++() { NonZeroIterator &operator++() {
++ptr_; ++ptr_;
...@@ -78,6 +85,7 @@ private: ...@@ -78,6 +85,7 @@ private:
int value_; int value_;
}; };
using NonCopyableIntPair = std::pair<NonCopyableInt, NonCopyableInt>; using NonCopyableIntPair = std::pair<NonCopyableInt, NonCopyableInt>;
PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableInt>); PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableInt>);
PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>); PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>);
...@@ -375,6 +383,17 @@ TEST_SUBMODULE(sequences_and_iterators, m) { ...@@ -375,6 +383,17 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
private: private:
std::vector<std::pair<int, int>> data_; std::vector<std::pair<int, int>> data_;
}; };
{
// #4383 : Make sure `py::make_*iterator` functions work with move-only iterators
using iterator_t = NonZeroIterator<std::pair<int, int>>;
static_assert(std::is_move_assignable<iterator_t>::value, "");
static_assert(std::is_move_constructible<iterator_t>::value, "");
static_assert(!std::is_copy_assignable<iterator_t>::value, "");
static_assert(!std::is_copy_constructible<iterator_t>::value, "");
}
py::class_<IntPairs>(m, "IntPairs") py::class_<IntPairs>(m, "IntPairs")
.def(py::init<std::vector<std::pair<int, int>>>()) .def(py::init<std::vector<std::pair<int, int>>>())
.def( .def(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment