I wrote this C ++ 17 code and expected it to work out of the box.
class putc_iterator : public boost::iterator_facade< putc_iterator, void, std::output_iterator_tag > { friend class boost::iterator_core_access; struct proxy { void operator= (char ch) { putc(ch, stdout); } }; auto dereference() const { return proxy{}; } void increment() {} bool equal(const putc_iterator&) const { return false; } };
I am trying to match the behavior of all the standard OutputIterators by setting my member iterator typedefs value_type and reference to void (since these types do not make sense to an iterator whose operator* does not return a link).
However, Boost complains:
In file included from prog.cc:2: /opt/wandbox/boost-1.63.0/clang-head/include/boost/iterator/iterator_facade.hpp:333:50: error: cannot form a reference to 'void' static result_type apply(Reference const & x) ^
It seems that Boost is trying to hardcode the generated operator* signature as reference operator*() const . That is, boost::iterator_facade can output the correct return type operator*() by simply passing everything that dereference() was returned; but for some reason he just doesn't play.
What solution? I can not pass proxy as a template parameter to the base class, since proxy is not yet defined. I could pull the proxy into the part namespace:
namespace detail { struct proxy { void operator= (char ch) { putc(ch, stdout); } }; } class putc_iterator : public boost::iterator_facade< putc_iterator, void, std::output_iterator_tag, detail::proxy > { friend class boost::iterator_core_access; auto dereference() const { return detail::proxy{}; } void increment() {} bool equal(const putc_iterator&) const { return false; } };
but it seems uncomfortable and definitely is something that "should not be necessary."
Is this a bug in iterator_facade ? Is this a non-error function? If the latter, then how should I use it to create OutputIterators?
Also, a minor nitpick: even my workaround with the part namespace is βwrong" in the sense that it does std::is_same_v<putc_iterator::reference, detail::proxy> when what I want (for parity with standard iterators), is std::is_same_v<putc_iterator::reference, void> .
c ++ boost c ++ 1z boost-iterators
Quuxplusone Apr 18 '17 at 19:52 2017-04-18 19:52
source share