Bolt  1.3
C++ template library with support for OpenCL
iterator_facade.h
1 /***************************************************************************
2 * © 2012,2014 Advanced Micro Devices, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 
16 ***************************************************************************/
17 
18 // (C) Copyright David Abrahams 2002.
19 // (C) Copyright Jeremy Siek 2002.
20 // (C) Copyright Thomas Witt 2002.
21 // Distributed under the Boost Software License, Version 1.0. (See
22 // accompanying file BOOST_LICENSE_1_0.txt or copy at
23 // http://www.boost.org/LICENSE_1_0.txt)
24 
25 #ifndef BOLT_ITERATOR_FACADE_H
26 #define BOLT_ITERATOR_FACADE_H
27 
28 #include <type_traits>
29 #include <bolt/cl/iterator/iterator_categories.h>
30 #include <bolt/cl/iterator/facade_iterator_category.h>
31 
32 namespace bolt
33 {
34 namespace cl
35 {
36  // This forward declaration is required for the friend declaration
37  // in iterator_core_access
38  template <class I, class V, class TC, class R, class D> class iterator_facade;
39 
40  namespace detail
41  {
42  // A binary metafunction class that always returns bool. VC6
43  // ICEs on mpl::always<bool>, probably because of the default
44  // parameters.
45  struct always_bool2
46  {
47  template <class T, class U>
48  struct apply
49  {
50  typedef bool type;
51  };
52  };
53 
54  //
55  // enable if for use in operator implementation.
56  //
57  template <
58  class Facade1
59  , class Facade2
60  , class Return
61  >
63  : std::enable_if<
64  bolt::cl::detail::or_<
65  std::is_convertible<Facade1, Facade2>
66  , std::is_convertible<Facade2, Facade1>
67  >::value
68  , Return
69  >
70  {};
71 
72  template<typename Facade1, typename Facade2>
74  : bolt::cl::detail::eval_if<
75  std::is_convertible<Facade2,Facade1>,
76  identity_<typename Facade1::difference_type>,
77  identity_<typename Facade2::difference_type>
78  >
79  {};
80 
81 
82 
83 
84  // A proxy return type for operator[], needed to deal with
85  // iterators that may invalidate referents upon destruction.
86  // Consider the temporary iterator in *(a + n)
87  template <class Iterator>
89  {
90  // Iterator is actually an iterator_facade, so we do not have to
91  // go through iterator_traits to access the traits.
92  typedef typename Iterator::reference reference;
93  typedef typename Iterator::value_type value_type;
94 
95  public:
96  operator_brackets_proxy(Iterator const& iter)
97  : m_iter(iter)
98  {}
99 
100  operator reference() const
101  {
102  return *m_iter;
103  }
104 
105  operator_brackets_proxy& operator=(value_type const& val)
106  {
107  *m_iter = val;
108  return *this;
109  }
110 
111  private:
112  Iterator m_iter;
113  };
114 
115 
117  {
118  template <class I1, class I2>
119  struct apply
120  : bolt::cl::detail::eval_if<
121  std::is_convertible<I2,I1>
122  , bolt::cl::iterator_difference<I1>
123  , bolt::cl::iterator_difference<I2>
124  >
125  {};
126 
127  };
128  } // namespace detail
129 
130 
131 # define BOLT_ITERATOR_FACADE_INTEROP_HEAD(prefix, op) \
132  template < \
133  class Derived1, class V1, class TC1, class Reference1, class Difference1 \
134  , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
135  > \
136  prefix bool \
137  operator op( \
138  iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
139  , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
140 
141 
142  //
143  // Helper class for granting access to the iterator core interface.
144  //
145  // The simple core interface is used by iterator_facade. The core
146  // interface of a user/library defined iterator type should not be made public
147  // so that it does not clutter the public interface. Instead iterator_core_access
148  // should be made friend so that iterator_facade can access the core
149  // interface through iterator_core_access.
150  //
152  {
153  template <class I, class V, class TC, class R, class D> friend class iterator_facade;
154 
155 # define BOLT_ITERATOR_FACADE_RELATION(op) \
156  BOLT_ITERATOR_FACADE_INTEROP_HEAD(friend,op);
157 
158  BOLT_ITERATOR_FACADE_RELATION(==)
159  BOLT_ITERATOR_FACADE_RELATION(!=)
160 
161  BOLT_ITERATOR_FACADE_RELATION(<)
162  BOLT_ITERATOR_FACADE_RELATION(>)
163  BOLT_ITERATOR_FACADE_RELATION(<=)
164  BOLT_ITERATOR_FACADE_RELATION(>=)
165 # undef BOLT_ITERATOR_FACADE_RELATION
166 
167  template <
168  class Derived1, class V1, class TC1, class Reference1, class Difference1
169  , class Derived2, class V2, class TC2, class Reference2, class Difference2
170  >
174  >::type
175  operator -(
178 
179 
180  template <class Derived, class V, class TC, class R, class D>
181  friend inline Derived operator+ (iterator_facade<Derived, V, TC, R, D> const&
182  , typename Derived::difference_type);
183 
184  template <class Derived, class V, class TC, class R, class D>
185  friend inline Derived operator+ (typename Derived::difference_type
187 
188  template <class Facade>
189  static typename Facade::reference dereference(Facade const& f)
190  {
191  return f.dereference();
192  }
193 
194  template <class Facade>
195  static void increment(Facade& f)
196  {
197  f.increment();
198  }
199 
200  template <class Facade>
201  static void decrement(Facade& f)
202  {
203  f.decrement();
204  }
205 
206  template <class Facade1, class Facade2>
207  static bool equal(Facade1 const& f1, Facade2 const& f2)
208  {
209  return f1.equal(f2);
210  }
211 
212  template <class Facade1, class Facade2>
213  static bool equal(Facade1 const& f1, Facade2 const& f2, std::true_type)
214  {
215  return f1.equal(f2);
216  }
217 
218  template <class Facade1, class Facade2>
219  static bool equal(Facade1 const& f1, Facade2 const& f2, std::false_type)
220  {
221  return f2.equal(f1);
222  }
223 
224  template <class Facade>
225  static void advance(Facade& f, typename Facade::difference_type n)
226  {
227  f.advance(n);
228  }
229 
230  template <class Facade1, class Facade2>
231  static typename Facade1::difference_type distance_from(
232  Facade1 const& f1, Facade2 const& f2, std::true_type)
233  {
234  return -f1.distance_to(f2);
235  }
236 
237  template <class Facade1, class Facade2>
238  static typename Facade2::difference_type distance_from(
239  Facade1 const& f1, Facade2 const& f2, std::false_type)
240  {
241  return f2.distance_to(f1);
242  }
243 
244  //
245  // Curiously Recurring Template interface.
246  //
247  template <class I, class V, class TC, class R, class D>
248  static I& derived(bolt::cl::iterator_facade<I,V,TC,R,D>& facade)
249  {
250  return *static_cast<I*>(&facade);
251  }
252 
253  template <class I, class V, class TC, class R, class D>
254  static I const& derived(bolt::cl::iterator_facade<I,V,TC,R,D> const& facade)
255  {
256  return *static_cast<I const*>(&facade);
257  }
258 
259  private:
260  // objects of this class are useless
261  iterator_core_access(); //undefined
262  }; // end class iterator_core_access
263 
264  //
265  // iterator_facade - use as a public base class for defining new
266  // standard-conforming iterators.
267  //
268  template <
269  class Derived // The derived iterator type being constructed
270  , class Value
271  , class CategoryOrTraversal
272  , class Reference = Value&
273  , class Difference = std::ptrdiff_t
274  >
276  {
277  private:
278  //
279  // Curiously Recurring Template interface.
280  //
281  Derived& derived()
282  {
283  return *static_cast<Derived*>(this);
284  }
285 
286  Derived const& derived() const
287  {
288  return *static_cast<Derived const*>(this);
289  }
290 
291  protected:
292  // For use by derived classes
294 
295  public:
296 
297  typedef typename std::remove_const<Value>::type value_type;
298  typedef Reference reference;
299  typedef Difference difference_type;
300  typedef typename std::add_pointer<value_type>::type pointer;
301 
303 
304  reference operator*() const
305  {
306  return iterator_core_access::dereference(this->derived());
307  }
308 
309  pointer operator->() const
310  {
311  return this->derived();
312  }
313 
314  reference
315  operator[](difference_type n) const
316  {
317  return *(this->derived() + n);
318  }
319 
320  Derived& operator++()
321  {
322  iterator_core_access::increment(this->derived());
323  return this->derived();
324  }
325 
326  Derived
327  operator++(int)
328  {
329  Derived tmp(this->derived());
330  ++*this;
331  return tmp;
332  }
333 
334  Derived& operator--()
335  {
336  iterator_core_access::decrement(this->derived());
337  return this->derived();
338  }
339 
340  Derived operator--(int)
341  {
342  Derived tmp(this->derived());
343  --*this;
344  return tmp;
345  }
346 
347  Derived& operator+=(difference_type n)
348  {
349  iterator_core_access::advance(this->derived(), n);
350  return this->derived();
351  }
352 
353  Derived& operator-=(difference_type n)
354  {
355  iterator_core_access::advance(this->derived(), -n);
356  return this->derived();
357  }
358 
359  Derived operator-(difference_type x) const
360  {
361  Derived result(this->derived());
362  return result -= x;
363  }
364 
365  }; // end of iterator_facade
366 
367 
368  //
369  // Comparison operator implementation. The library supplied operators
370  // enables the user to provide fully interoperable constant/mutable
371  // iterator types. I.e. the library provides all operators
372  // for all mutable/constant iterator combinations.
373  //
374  // Note though that this kind of interoperability for constant/mutable
375  // iterators is not required by the standard for container iterators.
376  // All the standard asks for is a conversion mutable -> constant.
377  // Most standard library implementations nowadays provide fully interoperable
378  // iterator implementations, but there are still heavily used implementations
379  // that do not provide them. (Actually it's even worse, they do not provide
380  // them for only a few iterators.)
381  //
382  // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
383  // enable the user to turn off mixed type operators
384  //
385  // The library takes care to provide only the right operator overloads.
386  // I.e.
387  //
388  // bool operator==(Iterator, Iterator);
389  // bool operator==(ConstIterator, Iterator);
390  // bool operator==(Iterator, ConstIterator);
391  // bool operator==(ConstIterator, ConstIterator);
392  //
393  // ...
394  //
395  // In order to do so it uses c++ idioms that are not yet widely supported
396  // by current compiler releases. The library is designed to degrade gracefully
397  // in the face of compiler deficiencies. In general compiler
398  // deficiencies result in less strict error checking and more obscure
399  // error messages, functionality is not affected.
400  //
401  // For full operation compiler support for "Substitution Failure Is Not An Error"
402  // (aka. enable_if) and boost::is_convertible is required.
403  //
404  // The following problems occur if support is lacking.
405  //
406  // Pseudo code
407  //
408  // ---------------
409  // AdaptorA<Iterator1> a1;
410  // AdaptorA<Iterator2> a2;
411  //
412  // // This will result in a no such overload error in full operation
413  // // If enable_if or is_convertible is not supported
414  // // The instantiation will fail with an error hopefully indicating that
415  // // there is no operator== for Iterator1, Iterator2
416  // // The same will happen if no enable_if is used to remove
417  // // false overloads from the templated conversion constructor
418  // // of AdaptorA.
419  //
420  // a1 == a2;
421  // ----------------
422  //
423  // AdaptorA<Iterator> a;
424  // AdaptorB<Iterator> b;
425  //
426  // // This will result in a no such overload error in full operation
427  // // If enable_if is not supported the static assert used
428  // // in the operator implementation will fail.
429  // // This will accidently work if is_convertible is not supported.
430  //
431  // a == b;
432  // ----------------
433  //
434 
435 # define BOLT_ITERATOR_FACADE_INTEROP(op, return_prefix, base_op) \
436  BOLT_ITERATOR_FACADE_INTEROP_HEAD(inline, op) \
437  { \
438  /* For those compilers that do not support enable_if */ \
439  return_prefix iterator_core_access::base_op( \
440  *static_cast<Derived1 const*>(&lhs) \
441  , *static_cast<Derived2 const*>(&rhs) \
442  , std::is_convertible<Derived2,Derived1>() \
443  ); \
444  }
445 
446 # define BOLT_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
447  BOLT_ITERATOR_FACADE_INTEROP( \
448  op \
449  , return_prefix \
450  , base_op \
451  )
452 
453  BOLT_ITERATOR_FACADE_RELATION(==, return, equal);
454  BOLT_ITERATOR_FACADE_RELATION(!=, return !, equal);
455  BOLT_ITERATOR_FACADE_RELATION(<, return 0 >, distance_from);
456  BOLT_ITERATOR_FACADE_RELATION(>, return 0 <, distance_from);
457  BOLT_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_from);
458  BOLT_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_from);
459 
460 # undef BOLT_ITERATOR_FACADE_RELATION
461 
462 
463  template <
464  class Derived1, class V1, class TC1, class Reference1, class Difference1
465  , class Derived2, class V2, class TC2, class Reference2, class Difference2
466  >
470  >::type
471  operator -(
474  {
475  return iterator_core_access::distance_from(
476  *static_cast<Derived1 const*>(&lhs)
477  , *static_cast<Derived2 const*>(&rhs)
478  , std::is_convertible<Derived2,Derived1>()
479  );
480  }
481 
482 # undef BOLT_ITERATOR_FACADE_INTEROP
483 # undef BOLT_ITERATOR_FACADE_INTEROP_HEAD
484 
485  template <class Derived, class V, class TC, class R, class D>
486  inline Derived operator+ (bolt::cl::iterator_facade<Derived, V, TC, R, D> const& i,
487  typename Derived::difference_type n )
488  {
489  Derived tmp(static_cast<Derived const&>(i));
490  return tmp += n;
491  }
492 
493  template <class Derived, class V, class TC, class R, class D> \
494  inline Derived operator+ ( typename Derived::difference_type n,
496  {
497  Derived tmp(static_cast<Derived const&>(i));
498  return tmp += n;
499  }
500 
501 } // namespace cl
502 } // namespace bolt
503 
504 
505 #endif // BOLT_ITERATOR_FACADE_H