Opened 7 years ago
Last modified 7 years ago
#12071 new Bugs
Using iterator_facade with range-v3 fails to compile
Reported by: | Owned by: | jeffrey.hellrung | |
---|---|---|---|
Milestone: | To Be Determined | Component: | iterator |
Version: | Boost 1.61.0 | Severity: | Problem |
Keywords: | range-v3 | Cc: |
Description
The fact that postfix_increment_proxy
is not DefaultConstructible
and doesn't have a nested public value_type
makes iterators unusable with range-v3, which check the concepts.
Example:
#include "boost/iterator/iterator_facade.hpp" #include "range/v3/utility/iterator.hpp" template <class V, class Category> class TestIter : public boost::iterator_facade<TestIter<V, Category>, V, Category, V> { public: using typename boost::iterator_facade<TestIter<V, Category>, V, Category, V>::difference_type; TestIter() : v_() {} explicit TestIter(V v) : v_(v) {} private: friend class boost::iterator_core_access; V dereference() const { return v_; } bool equal(const TestIter& other) const { return v_ == other.v_; } void increment() { ++v_; } void decrement() { --v_; } void advance(difference_type n) { v_ += n; } difference_type distance_to(const TestIter& other) const { return other.v_ - v_; } V v_; }; using InIter = TestIter<int, std::input_iterator_tag>; static_assert(ranges::InputIterator<InIter>(), ""); void f(InIter x) { static_assert(ranges::Readable<decltype(x++)>(), ""); static_assert(ranges::DefaultConstructible<decltype(x++)>(), ""); }
I think static_assert(ranges::InputIterator<InIter>(), "")
fails, because the two static_asserts in f()
fail.
From what I've learned here:
https://github.com/ericniebler/range-v3/issues/304
it seems a good idea to fix postfix_increment_proxy
to conform to these requirements. Ditto writable_postfix_increment_proxy
.
Change History (2)
comment:1 by , 7 years ago
comment:2 by , 7 years ago
Summary: | postfix_increment_proxy is not DefaultConstructible and doesn't have a nested public value_type → Using iterator_facade with range-v3 fails to compile |
---|
Maybe a high-level example will be helpful:
#include <iostream> #include "third_party/boost/allowed/iterator/iterator_facade.hpp" #include "third_party/range_v3/include/range/v3/algorithm/copy.hpp" #include "third_party/range_v3/include/range/v3/iterator_range.hpp" #include "third_party/range_v3/include/range/v3/utility/iterator.hpp" template <class V, class Category> class TestIter : public boost::iterator_facade<TestIter<V, Category>, V, Category, V> { public: using typename boost::iterator_facade<TestIter<V, Category>, V, Category, V>::difference_type; TestIter() : v_() {} explicit TestIter(V v) : v_(v) {} private: friend class boost::iterator_core_access; V dereference() const { return v_; } bool equal(const TestIter& other) const { return v_ == other.v_; } void increment() { ++v_; } void decrement() { --v_; } void advance(difference_type n) { v_ += n; } difference_type distance_to(const TestIter& other) const { return other.v_ - v_; } V v_; }; using InIter = TestIter<int, std::input_iterator_tag>; template <class R> void print(R&& r) { ranges::copy(std::forward<R>(r), ranges::ostream_iterator<>(std::cout, ", ")); std::cout << "\n"; } int main() { print(ranges::make_iterator_range(InIter(1), InIter(10))); }
Note:
See TracTickets
for help on using tickets.
Here's a simple fix, which works as long as the value type is DefaultConstructible:
To work around values which aren't DefaultConstructible, it might be necessary to wrap the
stored_value
inoptional
, but the above simple fix will work for majority of cases.