diff --git a/.ci/get-boost.sh b/.ci/get-boost.sh index 77604b5c30..ba5c76f846 100755 --- a/.ci/get-boost.sh +++ b/.ci/get-boost.sh @@ -45,6 +45,7 @@ git submodule --quiet update --init $GIT_SUBMODULE_OPTS \ libs/mp11 \ libs/mpl \ libs/preprocessor \ + libs/stl_interfaces \ libs/type_traits \ libs/variant2 # Transitive (of GIL tests too) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a21a27549c..a24e8143b2 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -21,7 +21,7 @@ jobs: - name: install packages run: | sudo apt update - sudo apt install g++ libpng-dev libjpeg-dev libtiff5-dev libraw-dev lcov python -y + sudo apt install g++ libpng-dev libjpeg-dev libtiff5-dev libraw-dev lcov python-is-python3 -y - name: Setup Boost run: | diff --git a/example/interleaved_ptr.hpp b/example/interleaved_ptr.hpp index 643af90099..2b9f6f9fb8 100644 --- a/example/interleaved_ptr.hpp +++ b/example/interleaved_ptr.hpp @@ -14,6 +14,8 @@ #include +#include + #include "interleaved_ref.hpp" // Example on how to create a pixel iterator @@ -34,25 +36,25 @@ namespace boost { namespace gil { template // A layout (includes the color space and channel ordering) -struct interleaved_ptr : boost::iterator_facade +struct interleaved_ptr : stl_interfaces::iterator_interface < +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS interleaved_ptr, - pixel::value_type, Layout>, - boost::random_access_traversal_tag, +#endif + std::random_access_iterator_tag, + pixel::value_type, Layout>, interleaved_ref::reference, Layout> const > { private: - using parent_t = boost::iterator_facade + using parent_t = stl_interfaces::iterator_interface < +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS interleaved_ptr, +#endif + std::random_access_iterator_tag, pixel::value_type, Layout>, - boost::random_access_traversal_tag, - interleaved_ref - < - typename std::iterator_traits::reference, - Layout - > const + interleaved_ref::reference, Layout> const >; using channel_t = typename std::iterator_traits::value_type; @@ -61,6 +63,9 @@ struct interleaved_ptr : boost::iterator_facade using reference = typename parent_t::reference; using difference_type = typename parent_t::difference_type; + using parent_t::operator++; + using parent_t::operator--; + interleaved_ptr() {} interleaved_ptr(const interleaved_ptr& ptr) : _channels(ptr._channels) {} template interleaved_ptr(const interleaved_ptr& ptr) : _channels(ptr._channels) {} @@ -71,24 +76,29 @@ struct interleaved_ptr : boost::iterator_facade interleaved_ptr(reference* pix) : _channels(&((*pix)[0])) {} interleaved_ptr& operator=(reference* pix) { _channels=&((*pix)[0]); return *this; } - /// For some reason operator[] provided by boost::iterator_facade returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - reference operator[](difference_type d) const { return memunit_advanced_ref(*this,d*sizeof(channel_t));} - - // Put this for every iterator whose reference is a proxy type - reference operator->() const { return **this; } - // Channels accessor (not required by any concept) const ChannelPtr& channels() const { return _channels; } ChannelPtr& channels() { return _channels; } // Not required by concepts but useful static const std::size_t num_channels = mp11::mp_size::value; + + constexpr auto operator*() const noexcept { return dereference(); } + + constexpr auto operator+=(difference_type d) -> interleaved_ptr& { advance(d); return *this; } + + constexpr auto operator++() noexcept -> interleaved_ptr& { increment(); return *this; } + constexpr auto operator--() noexcept -> interleaved_ptr& { decrement(); return *this; } + + constexpr auto operator-(interleaved_ptr other) const noexcept { return -distance_to(other); } + + constexpr bool operator==(interleaved_ptr other) const noexcept { return equal(other); } + private: ChannelPtr _channels; - friend class boost::iterator_core_access; template friend struct interleaved_ptr; + friend struct boost::stl_interfaces::access; void increment() { _channels+=num_channels; } void decrement() { _channels-=num_channels; } void advance(std::ptrdiff_t d) { _channels+=num_channels*d; } diff --git a/include/boost/gil/algorithm.hpp b/include/boost/gil/algorithm.hpp index 2b61068830..23084264b8 100644 --- a/include/boost/gil/algorithm.hpp +++ b/include/boost/gil/algorithm.hpp @@ -189,7 +189,11 @@ namespace detail { /// \ingroup CopyPixels template struct copier_n { - BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits::difference_type n, O dst) const { std::copy(src,src+n, dst); } + BOOST_FORCEINLINE void operator()(I src, typename std::iterator_traits::difference_type n, O dst) const { + if (n < 0) + return; + std::copy(src, src + n, dst); + } }; /// Source range is delimited by image iterators diff --git a/include/boost/gil/bit_aligned_pixel_iterator.hpp b/include/boost/gil/bit_aligned_pixel_iterator.hpp index 7d3059b66e..2aed7d76fe 100644 --- a/include/boost/gil/bit_aligned_pixel_iterator.hpp +++ b/include/boost/gil/bit_aligned_pixel_iterator.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -34,20 +34,31 @@ namespace boost { namespace gil { /// \ingroup PixelIteratorNonAlignedPixelIterator PixelBasedModel template -struct bit_aligned_pixel_iterator : public iterator_facade, - typename NonAlignedPixelReference::value_type, - std::random_access_iterator_tag, - const NonAlignedPixelReference, - typename NonAlignedPixelReference::bit_range_t::difference_type> { +class bit_aligned_pixel_iterator : public stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + bit_aligned_pixel_iterator, +#endif + std::random_access_iterator_tag, + typename NonAlignedPixelReference::value_type, + const NonAlignedPixelReference, + typename NonAlignedPixelReference::value_type*, + typename NonAlignedPixelReference::bit_range_t::difference_type> +{ private: - using parent_t = iterator_facade, - typename NonAlignedPixelReference::value_type, - std::random_access_iterator_tag, - const NonAlignedPixelReference, - typename NonAlignedPixelReference::bit_range_t::difference_type>; - template friend struct bit_aligned_pixel_iterator; + using parent_t = stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + bit_aligned_pixel_iterator, +#endif + std::random_access_iterator_tag, + typename NonAlignedPixelReference::value_type, + const NonAlignedPixelReference, + typename NonAlignedPixelReference::value_type*, + typename NonAlignedPixelReference::bit_range_t::difference_type>; + + template friend class bit_aligned_pixel_iterator; using bit_range_t = typename NonAlignedPixelReference::bit_range_t; + public: using difference_type = typename parent_t::difference_type; using reference = typename parent_t::reference; @@ -61,21 +72,20 @@ struct bit_aligned_pixel_iterator : public iterator_facadebit_range()) {} explicit bit_aligned_pixel_iterator(typename bit_range_t::byte_t* data, int bit_offset=0) : _bit_range(data,bit_offset) {} - /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - auto operator[](difference_type d) const -> reference { bit_aligned_pixel_iterator it=*this; it.advance(d); return *it; } + constexpr auto operator*() const noexcept -> reference { return dereference(); } + + constexpr auto operator+=(difference_type i) noexcept -> bit_aligned_pixel_iterator& { advance(i); return *this; } + + constexpr auto operator-(bit_aligned_pixel_iterator other) const noexcept { return -distance_to(other); } - auto operator->() const -> reference { return **this; } auto bit_range() const -> bit_range_t const& { return _bit_range; } - auto bit_range() -> bit_range_t& { return _bit_range; } + auto bit_range() -> bit_range_t& { return _bit_range; } + private: bit_range_t _bit_range; static constexpr int bit_size = NonAlignedPixelReference::bit_size; - friend class boost::iterator_core_access; auto dereference() const -> reference { return NonAlignedPixelReference(_bit_range); } - void increment() { ++_bit_range; } - void decrement() { --_bit_range; } void advance(difference_type d) { _bit_range.bit_advance(d*bit_size); } auto distance_to(bit_aligned_pixel_iterator const& it) const -> difference_type { return _bit_range.bit_distance_to(it._bit_range) / bit_size; } diff --git a/include/boost/gil/concepts/image_view.hpp b/include/boost/gil/concepts/image_view.hpp index ffcd41258e..47b4ba8610 100644 --- a/include/boost/gil/concepts/image_view.hpp +++ b/include/boost/gil/concepts/image_view.hpp @@ -120,13 +120,13 @@ struct RandomAccessNDImageViewConcept static const std::size_t N=View::num_dimensions; gil_function_requires>(); - gil_function_requires>(); - gil_function_requires>(); + gil_function_requires>(); + gil_function_requires>(); using first_it_type = typename View::template axis<0>::iterator; using last_it_type = typename View::template axis::iterator; - gil_function_requires>(); - gil_function_requires>(); + gil_function_requires>(); + gil_function_requires>(); // static_assert(typename std::iterator_traits::difference_type, typename point_t::template axis<0>::coord_t>::value, ""); // static_assert(typename std::iterator_traits::difference_type, typename point_t::template axis::coord_t>::value, ""); @@ -399,19 +399,19 @@ struct RandomAccessNDImageViewIsMutableConcept { gil_function_requires>(); - gil_function_requires>(); + gil_function_requires>(); - gil_function_requires>(); - gil_function_requires::iterator >>(); - gil_function_requires::iterator >>(); diff --git a/include/boost/gil/concepts/pixel_iterator.hpp b/include/boost/gil/concepts/pixel_iterator.hpp index 52255dfb28..f0c37a5972 100644 --- a/include/boost/gil/concepts/pixel_iterator.hpp +++ b/include/boost/gil/concepts/pixel_iterator.hpp @@ -15,8 +15,6 @@ #include #include -#include - #include #include #include @@ -45,48 +43,48 @@ template struct iterator_adaptor_get_base; // Isolating mutability to result in faster compile time namespace detail { -// Preconditions: TT Models boost_concepts::ForwardTraversalConcept -template -struct ForwardIteratorIsMutableConcept -{ - void constraints() - { - auto const tmp = *i; - *i++ = tmp; // require postincrement and assignment - } - TT i; -}; - -// Preconditions: TT Models boost::BidirectionalIteratorConcept -template -struct BidirectionalIteratorIsMutableConcept -{ - void constraints() - { - gil_function_requires< ForwardIteratorIsMutableConcept>(); - auto const tmp = *i; - *i-- = tmp; // require postdecrement and assignment - } - TT i; -}; - -// Preconditions: TT Models boost_concepts::RandomAccessTraversalConcept -template -struct RandomAccessIteratorIsMutableConcept -{ - void constraints() - { - gil_function_requires>(); - - typename std::iterator_traits::difference_type n = 0; - ignore_unused_variable_warning(n); - i[n] = *i; // require element access and assignment - } - TT i; -}; +//// Preconditions: TT Models ForwardIterator +//template +//struct ForwardIteratorIsMutableConcept +//{ +// void constraints() +// { +// auto const tmp = *i; +// *i++ = tmp; // require postincrement and assignment +// } +// TT i; +//}; +// +//// Preconditions: TT Models BidirectionalIterator +//template +//struct BidirectionalIteratorIsMutableConcept +//{ +// void constraints() +// { +// gil_function_requires< ForwardIteratorIsMutableConcept>(); +// auto const tmp = *i; +// *i-- = tmp; // require postdecrement and assignment +// } +// TT i; +//}; +// +//// Preconditions: TT Models RandomAccessIterator +//template +//struct RandomAccessIteratorIsMutableConcept +//{ +// void constraints() +// { +// gil_function_requires>(); +// +// typename std::iterator_traits::difference_type n = 0; +// ignore_unused_variable_warning(n); +// i[n] = *i; // require element access and assignment +// } +// TT i; +//}; // Iterators that can be used as the base of memory_based_step_iterator require some additional functions -// \tparam Iterator Models boost_concepts::RandomAccessTraversalConcept +// \tparam Iterator Models RandomAccessIterator template struct RandomAccessIteratorIsMemoryBasedConcept { @@ -111,7 +109,7 @@ struct PixelIteratorIsMutableConcept { void constraints() { - gil_function_requires>(); + gil_function_requires>(); using ref_t = typename std::remove_reference < @@ -157,7 +155,7 @@ struct HasTransposedTypeConcept /// /// \code /// concept PixelIteratorConcept -/// : boost_concepts::RandomAccessTraversalConcept, PixelBasedConcept +/// : RandomAccessIterator, PixelBasedConcept /// { /// where PixelValueConcept; /// typename const_iterator_type::type; @@ -171,7 +169,7 @@ struct PixelIteratorConcept { void constraints() { - gil_function_requires>(); + gil_function_requires>(); gil_function_requires>(); using value_type = typename std::iterator_traits::value_type; @@ -222,7 +220,7 @@ struct MutablePixelIteratorConcept /// \ingroup PixelIteratorConceptStepIterator /// \brief Concept of a random-access iterator that can be advanced in memory units (bytes or bits) /// \code -/// concept MemoryBasedIteratorConcept +/// concept MemoryBasedIteratorConcept /// { /// typename byte_to_memunit; where metafunction >; /// std::ptrdiff_t memunit_step(const Iterator&); @@ -237,7 +235,7 @@ struct MemoryBasedIteratorConcept { void constraints() { - gil_function_requires>(); + gil_function_requires>(); gil_function_requires>(); } }; @@ -247,7 +245,7 @@ struct MemoryBasedIteratorConcept /// /// Step iterators are iterators that have a set_step method /// \code -/// concept StepIteratorConcept +/// concept StepIteratorConcept /// { /// template /// void Iterator::set_step(D step); @@ -258,7 +256,7 @@ struct StepIteratorConcept { void constraints() { - gil_function_requires>(); + gil_function_requires>(); it.set_step(0); } Iterator it; @@ -277,7 +275,7 @@ struct MutableStepIteratorConcept void constraints() { gil_function_requires>(); - gil_function_requires>(); + gil_function_requires>(); } }; @@ -297,17 +295,17 @@ struct MutableStepIteratorConcept /// The adaptee can be obtained from the iterator via the "base()" method. /// /// \code -/// concept IteratorAdaptorConcept +/// concept IteratorAdaptorConcept /// { /// where SameType::type, std::true_type>; /// /// typename iterator_adaptor_get_base; /// where Metafunction >; -/// where boost_concepts::ForwardTraversalConcept::type>; +/// where ForwardIterator::type>; /// /// typename another_iterator; /// typename iterator_adaptor_rebind::type; -/// where boost_concepts::ForwardTraversalConcept; +/// where ForwardIterator; /// where IteratorAdaptorConcept::type>; /// /// const iterator_adaptor_get_base::type& Iterator::base() const; @@ -318,10 +316,10 @@ struct IteratorAdaptorConcept { void constraints() { - gil_function_requires>(); + gil_function_requires>(); using base_t = typename iterator_adaptor_get_base::type; - gil_function_requires>(); + gil_function_requires>(); static_assert(is_iterator_adaptor::value, ""); using rebind_t = typename iterator_adaptor_rebind::type; @@ -344,7 +342,7 @@ struct MutableIteratorAdaptorConcept void constraints() { gil_function_requires>(); - gil_function_requires>(); + gil_function_requires>(); } }; diff --git a/include/boost/gil/concepts/pixel_locator.hpp b/include/boost/gil/concepts/pixel_locator.hpp index d18f30dc30..72a680470e 100644 --- a/include/boost/gil/concepts/pixel_locator.hpp +++ b/include/boost/gil/concepts/pixel_locator.hpp @@ -136,8 +136,8 @@ struct RandomAccessNDLocatorConcept using first_it_type = typename Loc::template axis<0>::iterator; using last_it_type = typename Loc::template axis::iterator; - gil_function_requires>(); - gil_function_requires>(); + gil_function_requires>(); + gil_function_requires>(); // point_t must be an N-dimensional point, each dimension of which must // have the same type as difference_type of the corresponding iterator @@ -309,11 +309,11 @@ struct RandomAccessNDLocatorIsMutableConcept { void constraints() { - gil_function_requires::iterator >>(); - gil_function_requires::iterator >>(); diff --git a/include/boost/gil/extension/io/tiff/detail/is_allowed.hpp b/include/boost/gil/extension/io/tiff/detail/is_allowed.hpp index 87d08f8694..1547300636 100644 --- a/include/boost/gil/extension/io/tiff/detail/is_allowed.hpp +++ b/include/boost/gil/extension/io/tiff/detail/is_allowed.hpp @@ -98,7 +98,7 @@ struct Format_Type < typename is_bit_aligned::type>::type >, - is_floating_point + std::is_floating_point >::value >::type > @@ -125,7 +125,7 @@ struct Format_Type // return SAMPLEFORMAT_INT; // } // -// else if( is_floating_point< Channel >::value ) +// else if( std::is_floating_point< Channel >::value ) // { // return SAMPLEFORMAT_IEEEFP; // } diff --git a/include/boost/gil/io/scanline_read_iterator.hpp b/include/boost/gil/io/scanline_read_iterator.hpp index 593295fa5d..cae72728a5 100644 --- a/include/boost/gil/io/scanline_read_iterator.hpp +++ b/include/boost/gil/io/scanline_read_iterator.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -27,10 +27,10 @@ namespace boost { namespace gil { /// Input iterator to read images. template class scanline_read_iterator - : public boost::iterator_facade, byte_t*, std::input_iterator_tag> + : public boost::stl_interfaces::iterator_interface, byte_t*, std::input_iterator_tag> { private: - using base_t = boost::iterator_facade + using base_t = boost::stl_interfaces::iterator_interface < scanline_read_iterator, byte_t*, @@ -44,8 +44,12 @@ class scanline_read_iterator buffer_start_ = &buffer_->front(); } + constexpr auto operator*() const noexcept { return dereference(); } + constexpr auto operator++() noexcept -> scanline_read_iterator& { increment(); return *this; } + constexpr bool operator==(scanline_read_iterator other) const noexcept { return equal(other); } + private: - friend class boost::iterator_core_access; + friend struct boost::stl_interfaces::access; void increment() { diff --git a/include/boost/gil/io/typedefs.hpp b/include/boost/gil/io/typedefs.hpp index 8f331ed23f..c4feeac9f9 100644 --- a/include/boost/gil/io/typedefs.hpp +++ b/include/boost/gil/io/typedefs.hpp @@ -29,12 +29,12 @@ using byte_vector_t = std::vector; }} // namespace boost::gil -namespace boost { +namespace std { -template<> struct is_floating_point : std::true_type {}; -template<> struct is_floating_point : std::true_type {}; +template<> struct is_floating_point : std::true_type {}; +template<> struct is_floating_point : std::true_type {}; -} // namespace boost +} // namespace std namespace boost { namespace gil { diff --git a/include/boost/gil/iterator_from_2d.hpp b/include/boost/gil/iterator_from_2d.hpp index df52f2e4e8..980121b35f 100644 --- a/include/boost/gil/iterator_from_2d.hpp +++ b/include/boost/gil/iterator_from_2d.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace boost { namespace gil { @@ -39,20 +39,31 @@ namespace boost { namespace gil { /// within each row template // Models PixelLocatorConcept -class iterator_from_2d : public iterator_facade, - typename Loc2::value_type, - std::random_access_iterator_tag, - typename Loc2::reference, - typename Loc2::coord_t> { +class iterator_from_2d : public stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + iterator_from_2d, +#endif + std::random_access_iterator_tag, + typename Loc2::value_type, + typename Loc2::reference> +{ BOOST_GIL_CLASS_REQUIRE(Loc2, boost::gil, PixelLocatorConcept) + + using parent_t = stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + iterator_from_2d, +#endif + std::random_access_iterator_tag, + typename Loc2::value_type, + typename Loc2::reference>; + public: - using parent_t = iterator_facade, - typename Loc2::value_type, - std::random_access_iterator_tag, - typename Loc2::reference, - typename Loc2::coord_t>; - using reference = typename parent_t::reference; using difference_type = typename parent_t::difference_type; + using reference = typename parent_t::reference; + + using parent_t::operator++; + using parent_t::operator--; + using x_iterator = typename Loc2::x_iterator; using point_t = typename Loc2::point_t; @@ -60,10 +71,6 @@ class iterator_from_2d : public iterator_facade, std::ptrdiff_t x_pos() const { return _coords.x; } // current x position std::ptrdiff_t y_pos() const { return _coords.y; } // current y position - /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - reference operator[](difference_type d) const { return *(*this+d); } - bool is_1d_traversable() const { return _p.is_1d_traversable(width()); } // is there no gap at the end of each row? x_iterator& x() { return _p.x(); } @@ -73,9 +80,22 @@ class iterator_from_2d : public iterator_facade, template iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {} iterator_from_2d& operator=(iterator_from_2d const& other) = default; + constexpr auto operator*() const noexcept -> reference { return dereference(); } + + constexpr auto operator+=(difference_type d) -> iterator_from_2d& { advance(d); return *this; } + + constexpr auto operator++() noexcept -> iterator_from_2d& { increment(); return *this; } + constexpr auto operator--() noexcept -> iterator_from_2d& { decrement(); return *this; } + + constexpr auto operator-(iterator_from_2d other) const noexcept { return -distance_to(other); } + + constexpr bool operator==(iterator_from_2d other) const noexcept { return equal(other); } + private: template friend class iterator_from_2d; - friend class boost::iterator_core_access; + + friend struct boost::stl_interfaces::access; + reference dereference() const { return *_p; } void increment() { ++_coords.x; diff --git a/include/boost/gil/locator.hpp b/include/boost/gil/locator.hpp index f0e7c20366..beeafa706e 100644 --- a/include/boost/gil/locator.hpp +++ b/include/boost/gil/locator.hpp @@ -229,7 +229,7 @@ struct is_planar > : public is_planar {} template class memory_based_2d_locator : public pixel_2d_locator_base, typename iterator_adaptor_get_base::type, StepIterator> { using this_t = memory_based_2d_locator; - BOOST_GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept) + //BOOST_GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept) public: using parent_t = pixel_2d_locator_base, typename iterator_adaptor_get_base::type, StepIterator>; using const_t = memory_based_2d_locator::type>; // same as this type, but over const values diff --git a/include/boost/gil/metafunctions.hpp b/include/boost/gil/metafunctions.hpp index 9f9a4b9678..092f867ae5 100644 --- a/include/boost/gil/metafunctions.hpp +++ b/include/boost/gil/metafunctions.hpp @@ -9,6 +9,8 @@ #ifndef BOOST_GIL_METAFUNCTIONS_HPP #define BOOST_GIL_METAFUNCTIONS_HPP +#include + #include #include #include diff --git a/include/boost/gil/pixel_iterator_adaptor.hpp b/include/boost/gil/pixel_iterator_adaptor.hpp index 36c4cf02e0..08b3d77c2f 100644 --- a/include/boost/gil/pixel_iterator_adaptor.hpp +++ b/include/boost/gil/pixel_iterator_adaptor.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include @@ -26,50 +26,50 @@ namespace boost { namespace gil { template // Models Returns the result of dereferencing a given iterator of type Iterator -class dereference_iterator_adaptor : public iterator_adaptor, - Iterator, - typename DFn::value_type, - typename std::iterator_traits::iterator_category, - typename DFn::reference, - use_default> { - DFn _deref_fn; +class dereference_iterator_adaptor : public stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + dereference_iterator_adaptor, +#endif + typename std::iterator_traits::iterator_category, + typename DFn::value_type, + typename DFn::reference> +{ public: - using parent_t = iterator_adaptor, - Iterator, - typename DFn::value_type, - typename std::iterator_traits::iterator_category, - typename DFn::reference, - use_default>; + using parent_t = stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + dereference_iterator_adaptor, +#endif + typename std::iterator_traits::iterator_category, + typename DFn::value_type, + typename DFn::reference>; using reference = typename DFn::result_type; using difference_type = typename std::iterator_traits::difference_type; using dereference_fn = DFn; dereference_iterator_adaptor() {} template - dereference_iterator_adaptor(const dereference_iterator_adaptor& dit) : parent_t(dit.base()), _deref_fn(dit._deref_fn) {} - dereference_iterator_adaptor(Iterator it, DFn deref_fn=DFn()) : parent_t(it), _deref_fn(deref_fn) {} + dereference_iterator_adaptor(const dereference_iterator_adaptor& dit) : it_(dit.base()), _deref_fn(dit._deref_fn) {} + dereference_iterator_adaptor(Iterator it, DFn deref_fn=DFn()) : it_(it), _deref_fn(deref_fn) {} template - dereference_iterator_adaptor(const dereference_iterator_adaptor& it) : parent_t(it.base()), _deref_fn(it._deref_fn) {} - /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - reference operator[](difference_type d) const { return *(*this+d);} - - // although iterator_adaptor defines these, the default implementation computes distance and compares for zero. - // it is often faster to just apply the relation operator to the base - bool operator> (const dereference_iterator_adaptor& p) const { return this->base_reference()> p.base_reference(); } - bool operator< (const dereference_iterator_adaptor& p) const { return this->base_reference()< p.base_reference(); } - bool operator>=(const dereference_iterator_adaptor& p) const { return this->base_reference()>=p.base_reference(); } - bool operator<=(const dereference_iterator_adaptor& p) const { return this->base_reference()<=p.base_reference(); } - bool operator==(const dereference_iterator_adaptor& p) const { return this->base_reference()==p.base_reference(); } - bool operator!=(const dereference_iterator_adaptor& p) const { return this->base_reference()!=p.base_reference(); } + dereference_iterator_adaptor(const dereference_iterator_adaptor& it) : it_(it.base()), _deref_fn(it._deref_fn) {} + + constexpr auto operator*() const noexcept -> reference { return dereference(); } Iterator& base() { return this->base_reference(); } const Iterator& base() const { return this->base_reference(); } const DFn& deref_fn() const { return _deref_fn; } + +protected: + Iterator it_; + DFn _deref_fn; + + constexpr auto base_reference() noexcept -> Iterator& { return it_; } + constexpr auto base_reference() const noexcept -> Iterator const& { return it_; } + private: template friend class dereference_iterator_adaptor; - friend class boost::iterator_core_access; + friend struct boost::stl_interfaces::access; reference dereference() const { return _deref_fn(*(this->base_reference())); } }; diff --git a/include/boost/gil/planar_pixel_iterator.hpp b/include/boost/gil/planar_pixel_iterator.hpp index df4152b68f..22863c60f0 100644 --- a/include/boost/gil/planar_pixel_iterator.hpp +++ b/include/boost/gil/planar_pixel_iterator.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -42,11 +42,12 @@ struct planar_pixel_reference; template struct planar_pixel_iterator : - iterator_facade - < + stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS planar_pixel_iterator, - pixel::value_type,layout>, +#endif std::random_access_iterator_tag, + pixel::value_type,layout>, planar_pixel_reference::reference, ColorSpace> const >, detail::homogeneous_color_base @@ -57,11 +58,12 @@ struct planar_pixel_iterator > { private: - using parent_t = iterator_facade - < + using parent_t = stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS planar_pixel_iterator, - pixel::value_type,layout>, +#endif std::random_access_iterator_tag, + pixel::value_type,layout>, planar_pixel_reference::reference, ColorSpace> const >; @@ -79,6 +81,9 @@ struct planar_pixel_iterator using reference = typename parent_t::reference; using difference_type = typename parent_t::difference_type; + using parent_t::operator++; + using parent_t::operator--; + planar_pixel_iterator() : color_base_parent_t(0) {} planar_pixel_iterator(bool) {} // constructor that does not fill with zero (for performance) @@ -111,17 +116,19 @@ struct planar_pixel_iterator return *this; } - /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - reference operator[](difference_type d) const { return memunit_advanced_ref(*this,d*sizeof(channel_t));} + constexpr auto operator*() const noexcept -> reference { return dereference(); } + + constexpr auto operator+=(difference_type d) -> planar_pixel_iterator& { advance(d); return *this; } + + constexpr auto operator++() noexcept -> planar_pixel_iterator& { increment(); return *this; } + constexpr auto operator--() noexcept -> planar_pixel_iterator& { decrement(); return *this; } + + constexpr auto operator-(const planar_pixel_iterator& other) const noexcept { return -distance_to(other); } - reference operator->() const { return **this; } + constexpr bool operator==(const planar_pixel_iterator& other) const noexcept { return equal(other); } - // PERFORMANCE_CHECK: Remove? - bool operator< (const planar_pixel_iterator& ptr) const { return gil::at_c<0>(*this)< gil::at_c<0>(ptr); } - bool operator!=(const planar_pixel_iterator& ptr) const { return gil::at_c<0>(*this)!=gil::at_c<0>(ptr); } private: - friend class boost::iterator_core_access; + friend struct boost::stl_interfaces::access; void increment() { static_transform(*this,*this,detail::inc()); } void decrement() { static_transform(*this,*this,detail::dec()); } diff --git a/include/boost/gil/planar_pixel_reference.hpp b/include/boost/gil/planar_pixel_reference.hpp index 7dce352124..94ae23eeab 100644 --- a/include/boost/gil/planar_pixel_reference.hpp +++ b/include/boost/gil/planar_pixel_reference.hpp @@ -91,6 +91,7 @@ struct planar_pixel_reference : detail::homogeneous_color_base return *this; } + // TODO: Enable only for ConstChannelReference template planar_pixel_reference(Pixel const& p) : parent_t(p) { diff --git a/include/boost/gil/position_iterator.hpp b/include/boost/gil/position_iterator.hpp index 7685035058..621d431be0 100644 --- a/include/boost/gil/position_iterator.hpp +++ b/include/boost/gil/position_iterator.hpp @@ -10,7 +10,7 @@ #include -#include +#include #include @@ -28,18 +28,33 @@ namespace boost { namespace gil { /// \tparam Deref A function object that given a point returns a pixel reference. Models PixelDereferenceAdaptorConcept /// \tparam Dim Dimension to advance along template -struct position_iterator : public iterator_facade, - typename Deref::value_type, - std::random_access_iterator_tag, - typename Deref::reference, - typename Deref::argument_type::template axis::coord_t> { - using parent_t = iterator_facade, - typename Deref::value_type, - std::random_access_iterator_tag, - typename Deref::reference, - typename Deref::argument_type::template axis::coord_t>; +class position_iterator : public stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + position_iterator, +#endif + std::random_access_iterator_tag, + typename Deref::value_type, + typename Deref::reference, + typename Deref::value_type*, + typename Deref::argument_type::template axis::coord_t> +{ +public: + using parent_t = stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + position_iterator, +#endif + std::random_access_iterator_tag, + typename Deref::value_type, + typename Deref::reference, + typename Deref::value_type*, + typename Deref::argument_type::template axis::coord_t>; + using difference_type = typename parent_t::difference_type; using reference = typename parent_t::reference; + + using parent_t::operator++; + using parent_t::operator--; + using point_t = typename Deref::argument_type; position_iterator() {} @@ -63,21 +78,24 @@ struct position_iterator : public iterator_facade, auto deref_fn() const -> Deref const& { return _d; } void set_step(difference_type s) { _step[Dim]=s; } - /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - auto operator[](difference_type d) const -> reference - { - point_t p=_p; - p[Dim]+=d*_step[Dim]; - return _d(p); - } + + constexpr auto operator*() const noexcept -> reference { return dereference(); } + + constexpr auto operator+=(difference_type d) noexcept -> position_iterator& { advance(d); return *this; } + + constexpr auto operator++() noexcept -> position_iterator& { increment(); return *this; } + constexpr auto operator--() noexcept -> position_iterator& { decrement(); return *this; } + + constexpr auto operator-(position_iterator other) const noexcept { return -distance_to(other); } + + constexpr bool operator==(position_iterator other) const noexcept { return equal(other); } private: point_t _p, _step; Deref _d; - template friend struct position_iterator; - friend class boost::iterator_core_access; + template friend class position_iterator; + friend struct boost::stl_interfaces::access; reference dereference() const { return _d(_p); } void increment() { _p[Dim]+=_step[Dim]; } void decrement() { _p[Dim]-=_step[Dim]; } diff --git a/include/boost/gil/step_iterator.hpp b/include/boost/gil/step_iterator.hpp index 5472289b5e..c6e985711a 100644 --- a/include/boost/gil/step_iterator.hpp +++ b/include/boost/gil/step_iterator.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -38,65 +38,70 @@ template // A policy object that can compute the distance between two iterators of type Iterator // and can advance an iterator of type Iterator a given number of Iterator's units -class step_iterator_adaptor : public iterator_adaptor +class step_iterator_adaptor + : public stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + Derived, +#endif + std::random_access_iterator_tag, + typename std::iterator_traits::value_type, + typename std::iterator_traits::reference, + typename std::iterator_traits::pointer, + typename SFn::difference_type> { +private: + constexpr Derived& derived() noexcept + { + return static_cast(*this); + } + constexpr Derived const& derived() const noexcept + { + return static_cast(*this); + } + public: - using parent_t = iterator_adaptor; + using parent_t = stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + Derived, +#endif + std::random_access_iterator_tag, + typename std::iterator_traits::value_type, + typename std::iterator_traits::reference, + typename std::iterator_traits::pointer, + typename SFn::difference_type>; + using base_difference_type = typename std::iterator_traits::difference_type; using difference_type = typename SFn::difference_type; using reference = typename std::iterator_traits::reference; step_iterator_adaptor() {} - step_iterator_adaptor(Iterator const& it, SFn step_fn=SFn()) : parent_t(it), _step_fn(step_fn) {} + step_iterator_adaptor(Iterator const& it, SFn step_fn=SFn()) : it_(it), _step_fn(step_fn) {} auto step() const -> difference_type { return _step_fn.step(); } -protected: - SFn _step_fn; -private: - friend class boost::iterator_core_access; - - void increment() { _step_fn.advance(this->base_reference(),1); } - void decrement() { _step_fn.advance(this->base_reference(),-1); } - void advance(base_difference_type d) { _step_fn.advance(this->base_reference(),d); } - - auto distance_to(step_iterator_adaptor const& it) const -> difference_type - { - return _step_fn.difference(this->base_reference(),it.base_reference()); - } -}; + constexpr Derived& operator+=(base_difference_type d) { advance(d); return derived(); } -// although iterator_adaptor defines these, the default implementation computes distance and compares for zero. -// it is often faster to just apply the relation operator to the base -template inline -bool operator>(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { - return p1.step()>0 ? p1.base()> p2.base() : p1.base()< p2.base(); -} + constexpr auto operator-(step_iterator_adaptor other) const noexcept { return -distance_to(other); } -template inline -bool operator<(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { - return p1.step()>0 ? p1.base()< p2.base() : p1.base()> p2.base(); -} + // It is really common for iterator adaptors to have a base() member + // function that returns the adapted iterator. + constexpr auto base() noexcept { return base_reference(); } + constexpr auto base() const noexcept { return base_reference(); } -template inline -bool operator>=(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { - return p1.step()>0 ? p1.base()>=p2.base() : p1.base()<=p2.base(); -} +protected: + Iterator it_; + SFn _step_fn; -template inline -bool operator<=(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { - return p1.step()>0 ? p1.base()<=p2.base() : p1.base()>=p2.base(); -} + constexpr auto base_reference() noexcept -> Iterator& { return it_; } + constexpr auto base_reference() const noexcept -> Iterator const& { return it_; } -template inline -bool operator==(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { - return p1.base()==p2.base(); -} +private: + // Provide access to these private members. + friend boost::stl_interfaces::access; -template inline -bool operator!=(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { - return p1.base()!=p2.base(); -} + constexpr void advance(base_difference_type d) { _step_fn.advance(this->base_reference(),d); } + constexpr auto distance_to(step_iterator_adaptor const& it) const -> difference_type { return _step_fn.difference(this->base_reference(),it.base_reference()); } +}; } // namespace detail @@ -144,8 +149,8 @@ struct memunit_step_fn { template class memory_based_step_iterator : public detail::step_iterator_adaptor, - Iterator, - memunit_step_fn> + Iterator, + memunit_step_fn> { BOOST_GIL_CLASS_REQUIRE(Iterator, boost::gil, MemoryBasedIteratorConcept) public: @@ -162,10 +167,6 @@ class memory_based_step_iterator : public detail::step_iterator_adaptor& it) : parent_t(it.base(), memunit_step_fn(it.step())) {} - /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference - /// We require our own reference because it is registered in iterator_traits - auto operator[](difference_type d) const -> reference { return *(*this+d); } - void set_step(std::ptrdiff_t memunit_step) { this->_step_fn.set_step(memunit_step); } auto base() -> x_iterator& { return parent_t::base_reference(); } diff --git a/include/boost/gil/utilities.hpp b/include/boost/gil/utilities.hpp index 988efc3209..b24d5ca905 100644 --- a/include/boost/gil/utilities.hpp +++ b/include/boost/gil/utilities.hpp @@ -22,9 +22,6 @@ #pragma GCC diagnostic ignored "-Wconversion" #endif -#include -#include - #if defined(BOOST_CLANG) #pragma clang diagnostic pop #endif diff --git a/include/boost/gil/virtual_locator.hpp b/include/boost/gil/virtual_locator.hpp index f9a2fa9866..9395766976 100644 --- a/include/boost/gil/virtual_locator.hpp +++ b/include/boost/gil/virtual_locator.hpp @@ -12,7 +12,6 @@ #include #include -#include namespace boost { namespace gil { diff --git a/test/core/image_processing/convolve_2d.cpp b/test/core/image_processing/convolve_2d.cpp index cb6a96f66e..96fc469449 100644 --- a/test/core/image_processing/convolve_2d.cpp +++ b/test/core/image_processing/convolve_2d.cpp @@ -65,28 +65,28 @@ void test_convolve_2d_with_image_using_float32_t() { gil::float32_t img[] = { - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.76, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.6, 0.6, 0.1, 0.54, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.84, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.1, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.3, 0.1, 0.1, 0.4, 0.1, 0.32, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.21, 0.1, 0.1 + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.76f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.6f, 0.6f, 0.1f, 0.54f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.84f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.1f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.3f, 0.1f, 0.1f, 0.4f, 0.1f, 0.32f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.21f, 0.1f, 0.1f }; gil::float32_t exp_output[] = { - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.76, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.6, 0.6, 0.1, 0.54, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.84, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.1, 0.1, 0.1, 0.4, 0.1, 0.5, 0.1, 0.1, - 0.1, 0.3, 0.1, 0.1, 0.4, 0.1, 0.32, 0.1, 0.1, - 0.1, 0.2, 0.1, 0.1, 0.4, 0.1, 0.21, 0.1, 0.1 + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.76f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.6f, 0.6f, 0.1f, 0.54f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.84f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.1f, 0.1f, 0.1f, 0.4f, 0.1f, 0.5f, 0.1f, 0.1f, + 0.1f, 0.3f, 0.1f, 0.1f, 0.4f, 0.1f, 0.32f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, 0.1f, 0.4f, 0.1f, 0.21f, 0.1f, 0.1f }; gil::gray32f_image_t img_gray_out(9, 9);