Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / concepts / pixel_iterator.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_CONCEPTS_PIXEL_ITERATOR_HPP
9 #define BOOST_GIL_CONCEPTS_PIXEL_ITERATOR_HPP
10
11 #include <boost/gil/concepts/channel.hpp>
12 #include <boost/gil/concepts/color.hpp>
13 #include <boost/gil/concepts/concept_check.hpp>
14 #include <boost/gil/concepts/fwd.hpp>
15 #include <boost/gil/concepts/pixel.hpp>
16 #include <boost/gil/concepts/pixel_based.hpp>
17
18 #include <boost/iterator/iterator_concepts.hpp>
19
20 #include <cstddef>
21 #include <iterator>
22 #include <type_traits>
23
24 #if defined(BOOST_CLANG)
25 #pragma clang diagnostic push
26 #pragma clang diagnostic ignored "-Wunused-local-typedefs"
27 #endif
28
29 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
30 #pragma GCC diagnostic push
31 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
32 #endif
33
34 namespace boost { namespace gil {
35
36 // Forward declarations
37 template <typename It> struct const_iterator_type;
38 template <typename It> struct iterator_is_mutable;
39 template <typename It> struct is_iterator_adaptor;
40 template <typename It, typename NewBaseIt> struct iterator_adaptor_rebind;
41 template <typename It> struct iterator_adaptor_get_base;
42
43 // These iterator mutability concepts are taken from Boost concept_check.hpp.
44 // Isolating mutability to result in faster compile time
45 namespace detail {
46
47 // Preconditions: TT Models boost_concepts::ForwardTraversalConcept
48 template <class TT>
49 struct ForwardIteratorIsMutableConcept
50 {
51     void constraints()
52     {
53         auto const tmp = *i;
54         *i++ = tmp; // require postincrement and assignment
55     }
56     TT i;
57 };
58
59 // Preconditions: TT Models boost::BidirectionalIteratorConcept
60 template <class TT>
61 struct BidirectionalIteratorIsMutableConcept
62 {
63     void constraints()
64     {
65         gil_function_requires< ForwardIteratorIsMutableConcept<TT>>();
66         auto const tmp = *i;
67         *i-- = tmp; // require postdecrement and assignment
68     }
69     TT i;
70 };
71
72 // Preconditions: TT Models boost_concepts::RandomAccessTraversalConcept
73 template <class TT>
74 struct RandomAccessIteratorIsMutableConcept
75 {
76     void constraints()
77     {
78         gil_function_requires<BidirectionalIteratorIsMutableConcept<TT>>();
79
80         typename std::iterator_traits<TT>::difference_type n = 0;
81         ignore_unused_variable_warning(n);
82         i[n] = *i; // require element access and assignment
83     }
84     TT i;
85 };
86
87 // Iterators that can be used as the base of memory_based_step_iterator require some additional functions
88 // \tparam Iterator Models boost_concepts::RandomAccessTraversalConcept
89 template <typename Iterator>
90 struct RandomAccessIteratorIsMemoryBasedConcept
91 {
92     void constraints()
93     {
94         std::ptrdiff_t bs = memunit_step(it);
95         ignore_unused_variable_warning(bs);
96
97         it = memunit_advanced(it, 3);
98         std::ptrdiff_t bd = memunit_distance(it, it);
99         ignore_unused_variable_warning(bd);
100
101         memunit_advance(it,3);
102         // for performace you may also provide a customized implementation of memunit_advanced_ref
103     }
104     Iterator it;
105 };
106
107 /// \tparam Iterator Models PixelIteratorConcept
108 template <typename Iterator>
109 struct PixelIteratorIsMutableConcept
110 {
111     void constraints()
112     {
113         gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<Iterator>>();
114
115         using ref_t = typename std::remove_reference
116             <
117                 typename std::iterator_traits<Iterator>::reference
118             >::type;
119         using channel_t = typename element_type<ref_t>::type;
120         gil_function_requires<detail::ChannelIsMutableConcept<channel_t>>();
121     }
122 };
123
124 } // namespace detail
125
126 /// \ingroup PixelLocatorConcept
127 /// \brief Concept for locators and views that can define a type just like the given locator or view, except X and Y is swapped
128 /// \code
129 /// concept HasTransposedTypeConcept<typename T>
130 /// {
131 ///     typename transposed_type<T>;
132 ///         where Metafunction<transposed_type<T> >;
133 /// };
134 /// \endcode
135 template <typename T>
136 struct HasTransposedTypeConcept
137 {
138     void constraints()
139     {
140         using type = typename transposed_type<T>::type;
141         ignore_unused_variable_warning(type{});
142     }
143 };
144
145 /// \defgroup PixelIteratorConceptPixelIterator PixelIteratorConcept
146 /// \ingroup PixelIteratorConcept
147 /// \brief STL iterator over pixels
148
149 /// \ingroup PixelIteratorConceptPixelIterator
150 /// \brief An STL random access traversal iterator over a model of PixelConcept.
151 ///
152 /// GIL's iterators must also provide the following metafunctions:
153 ///  - \p const_iterator_type<Iterator>:   Returns a read-only equivalent of \p Iterator
154 ///  - \p iterator_is_mutable<Iterator>:   Returns whether the given iterator is read-only or mutable
155 ///  - \p is_iterator_adaptor<Iterator>:   Returns whether the given iterator is an adaptor over another iterator. See IteratorAdaptorConcept for additional requirements of adaptors.
156 ///
157 /// \code
158 /// concept PixelIteratorConcept<typename Iterator>
159 ///     : boost_concepts::RandomAccessTraversalConcept<Iterator>, PixelBasedConcept<Iterator>
160 /// {
161 ///     where PixelValueConcept<value_type>;
162 ///     typename const_iterator_type<It>::type;
163 ///         where PixelIteratorConcept<const_iterator_type<It>::type>;
164 ///     static const bool  iterator_is_mutable<It>::value;
165 ///     static const bool  is_iterator_adaptor<It>::value;   // is it an iterator adaptor
166 /// };
167 /// \endcode
168 template <typename Iterator>
169 struct PixelIteratorConcept
170 {
171     void constraints()
172     {
173         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<Iterator>>();
174         gil_function_requires<PixelBasedConcept<Iterator>>();
175
176         using value_type = typename std::iterator_traits<Iterator>::value_type;
177         gil_function_requires<PixelValueConcept<value_type>>();
178
179         using const_t = typename const_iterator_type<Iterator>::type;
180         static bool const is_mutable = iterator_is_mutable<Iterator>::value;
181         ignore_unused_variable_warning(is_mutable);
182
183         // immutable iterator must be constructible from (possibly mutable) iterator
184         const_t const_it(it);
185         ignore_unused_variable_warning(const_it);
186
187         check_base(typename is_iterator_adaptor<Iterator>::type());
188     }
189
190     void check_base(std::false_type) {}
191
192     void check_base(std::true_type)
193     {
194         using base_t = typename iterator_adaptor_get_base<Iterator>::type;
195         gil_function_requires<PixelIteratorConcept<base_t>>();
196     }
197
198     Iterator it;
199 };
200
201 /// \brief Pixel iterator that allows for changing its pixel
202 /// \ingroup PixelIteratorConceptPixelIterator
203 /// \code
204 /// concept MutablePixelIteratorConcept<PixelIteratorConcept Iterator>
205 ///     : MutableRandomAccessIteratorConcept<Iterator> {};
206 /// \endcode
207 template <typename Iterator>
208 struct MutablePixelIteratorConcept
209 {
210     void constraints()
211     {
212         gil_function_requires<PixelIteratorConcept<Iterator>>();
213         gil_function_requires<detail::PixelIteratorIsMutableConcept<Iterator>>();
214     }
215 };
216
217 /// \defgroup PixelIteratorConceptStepIterator StepIteratorConcept
218 /// \ingroup PixelIteratorConcept
219 /// \brief Iterator that advances by a specified step
220
221 /// \ingroup PixelIteratorConceptStepIterator
222 /// \brief Concept of a random-access iterator that can be advanced in memory units (bytes or bits)
223 /// \code
224 /// concept MemoryBasedIteratorConcept<boost_concepts::RandomAccessTraversalConcept Iterator>
225 /// {
226 ///     typename byte_to_memunit<Iterator>; where metafunction<byte_to_memunit<Iterator> >;
227 ///     std::ptrdiff_t      memunit_step(const Iterator&);
228 ///     std::ptrdiff_t      memunit_distance(const Iterator& , const Iterator&);
229 ///     void                memunit_advance(Iterator&, std::ptrdiff_t diff);
230 ///     Iterator            memunit_advanced(const Iterator& p, std::ptrdiff_t diff) { Iterator tmp; memunit_advance(tmp,diff); return tmp; }
231 ///     Iterator::reference memunit_advanced_ref(const Iterator& p, std::ptrdiff_t diff) { return *memunit_advanced(p,diff); }
232 /// };
233 /// \endcode
234 template <typename Iterator>
235 struct MemoryBasedIteratorConcept
236 {
237     void constraints()
238     {
239         gil_function_requires<boost_concepts::RandomAccessTraversalConcept<Iterator>>();
240         gil_function_requires<detail::RandomAccessIteratorIsMemoryBasedConcept<Iterator>>();
241     }
242 };
243
244 /// \ingroup PixelIteratorConceptStepIterator
245 /// \brief Step iterator concept
246 ///
247 /// Step iterators are iterators that have a set_step method
248 /// \code
249 /// concept StepIteratorConcept<boost_concepts::ForwardTraversalConcept Iterator>
250 /// {
251 ///     template <Integral D>
252 ///     void Iterator::set_step(D step);
253 /// };
254 /// \endcode
255 template <typename Iterator>
256 struct StepIteratorConcept
257 {
258     void constraints()
259     {
260         gil_function_requires<boost_concepts::ForwardTraversalConcept<Iterator>>();
261         it.set_step(0);
262     }
263     Iterator it;
264 };
265
266
267 /// \ingroup PixelIteratorConceptStepIterator
268 /// \brief Step iterator that allows for modifying its current value
269 /// \code
270 /// concept MutableStepIteratorConcept<Mutable_ForwardIteratorConcept Iterator>
271 ///     : StepIteratorConcept<Iterator> {};
272 /// \endcode
273 template <typename Iterator>
274 struct MutableStepIteratorConcept
275 {
276     void constraints()
277     {
278         gil_function_requires<StepIteratorConcept<Iterator>>();
279         gil_function_requires<detail::ForwardIteratorIsMutableConcept<Iterator>>();
280     }
281 };
282
283 /// \defgroup PixelIteratorConceptIteratorAdaptor IteratorAdaptorConcept
284 /// \ingroup PixelIteratorConcept
285 /// \brief Adaptor over another iterator
286
287 /// \ingroup PixelIteratorConceptIteratorAdaptor
288 /// \brief Iterator adaptor is a forward iterator adapting another forward iterator.
289 ///
290 /// In addition to GIL iterator requirements,
291 /// GIL iterator adaptors must provide the following metafunctions:
292 ///  - \p is_iterator_adaptor<Iterator>:             Returns \p std::true_type
293 ///  - \p iterator_adaptor_get_base<Iterator>:       Returns the base iterator type
294 ///  - \p iterator_adaptor_rebind<Iterator,NewBase>: Replaces the base iterator with the new one
295 ///
296 /// The adaptee can be obtained from the iterator via the "base()" method.
297 ///
298 /// \code
299 /// concept IteratorAdaptorConcept<boost_concepts::ForwardTraversalConcept Iterator>
300 /// {
301 ///     where SameType<is_iterator_adaptor<Iterator>::type, std::true_type>;
302 ///
303 ///     typename iterator_adaptor_get_base<Iterator>;
304 ///         where Metafunction<iterator_adaptor_get_base<Iterator> >;
305 ///         where boost_concepts::ForwardTraversalConcept<iterator_adaptor_get_base<Iterator>::type>;
306 ///
307 ///     typename another_iterator;
308 ///     typename iterator_adaptor_rebind<Iterator,another_iterator>::type;
309 ///         where boost_concepts::ForwardTraversalConcept<another_iterator>;
310 ///         where IteratorAdaptorConcept<iterator_adaptor_rebind<Iterator,another_iterator>::type>;
311 ///
312 ///     const iterator_adaptor_get_base<Iterator>::type& Iterator::base() const;
313 /// };
314 /// \endcode
315 template <typename Iterator>
316 struct IteratorAdaptorConcept
317 {
318     void constraints()
319     {
320         gil_function_requires<boost_concepts::ForwardTraversalConcept<Iterator>>();
321
322         using base_t = typename iterator_adaptor_get_base<Iterator>::type;
323         gil_function_requires<boost_concepts::ForwardTraversalConcept<base_t>>();
324
325         static_assert(is_iterator_adaptor<Iterator>::value, "");
326         using rebind_t = typename iterator_adaptor_rebind<Iterator, void*>::type;
327
328         base_t base = it.base();
329         ignore_unused_variable_warning(base);
330     }
331     Iterator it;
332 };
333
334 /// \brief Iterator adaptor that is mutable
335 /// \ingroup PixelIteratorConceptIteratorAdaptor
336 /// \code
337 /// concept MutableIteratorAdaptorConcept<Mutable_ForwardIteratorConcept Iterator>
338 ///     : IteratorAdaptorConcept<Iterator> {};
339 /// \endcode
340 template <typename Iterator>
341 struct MutableIteratorAdaptorConcept
342 {
343     void constraints()
344     {
345         gil_function_requires<IteratorAdaptorConcept<Iterator>>();
346         gil_function_requires<detail::ForwardIteratorIsMutableConcept<Iterator>>();
347     }
348 };
349
350 }} // namespace boost::gil
351
352 #if defined(BOOST_CLANG)
353 #pragma clang diagnostic pop
354 #endif
355
356 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
357 #pragma GCC diagnostic pop
358 #endif
359
360 #endif