Bolt  1.3
C++ template library with support for OpenCL
facade_iterator_category.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 // Copyright David Abrahams 2003. Use, modification and distribution is
19 // subject to the Boost Software License, Version 1.0. (See accompanying
20 // file BOOST_LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
21 #ifndef BOLT_FACADE_ITERATOR_CATEGORY_H
22 # define BOLT_FACADE_ITERATOR_CATEGORY_H
23 
24 
25 
26 #include <bolt/cl/iterator/iterator_categories.h>
27 
28 namespace bolt {
29 namespace cl {
30  struct use_default;
31 }
32 }
33 
34 namespace bolt {
35 namespace cl {
36 namespace detail {
37 
39  : std::input_iterator_tag
40 {
41  // Using inheritance for only input_iterator_tag helps to avoid
42  // ambiguities when a stdlib implementation dispatches on a
43  // function which is overloaded on both input_iterator_tag and
44  // output_iterator_tag, as STLPort does, in its __valid_range
45  // function. I claim it's better to avoid the ambiguity in these
46  // cases.
47  operator std::output_iterator_tag() const
48  {
49  return std::output_iterator_tag();
50  }
51 };
52 
53 //
54 // Convert an iterator_facade's traversal category, Value parameter,
55 // and ::reference type to an appropriate old-style category.
56 //
57 // If writability has been disabled per the above metafunction, the
58 // result will not be convertible to output_iterator_tag.
59 //
60 // Otherwise, if Traversal == single_pass_traversal_tag, the following
61 // conditions will result in a tag that is convertible both to
62 // input_iterator_tag and output_iterator_tag:
63 //
64 // 1. Reference is a reference to non-const
65 // 2. Reference is not a reference and is convertible to Value
66 //
67 template <typename Traversal, typename ValueParam, typename Reference>
69  : bolt::cl::detail::eval_if<
70  bolt::cl::detail::and_<
71  std::is_reference<Reference>
72  , std::is_convertible<Traversal,forward_traversal_tag>
73  >
74  , bolt::cl::detail::eval_if<
75  std::is_convertible<Traversal,random_access_traversal_tag>
76  , bolt::cl::detail::identity_<std::random_access_iterator_tag>
77  , bolt::cl::detail::if_<
78  std::is_convertible<Traversal,bidirectional_traversal_tag>
79  , std::bidirectional_iterator_tag
80  , std::forward_iterator_tag
81  >
82  >
83  , bolt::cl::detail::eval_if<
84  bolt::cl::detail::and_<
85  std::is_convertible<Traversal, single_pass_traversal_tag>
86  // check for readability
87  , std::is_convertible<Reference, ValueParam>
88  >
89  , bolt::cl::detail::identity_<std::input_iterator_tag>
90  , bolt::cl::detail::identity_<Traversal>
91  >
92  >
93 {
94 };
95 
96 // True iff T is convertible to an old-style iterator category.
97 template <class T>
99  : bolt::cl::detail::or_<
100  std::is_convertible<T,std::input_iterator_tag>
101  , std::is_convertible<T,std::output_iterator_tag>
102  >
103 {
104 };
105 
106 template <class T>
108  : std::is_convertible<T,incrementable_traversal_tag>
109 {};
110 
111 //
112 // A composite iterator_category tag convertible to Category (a pure
113 // old-style category) and Traversal (a pure traversal tag).
114 // Traversal must be a strict increase of the traversal power given by
115 // Category.
116 //
117 template <class Category, class Traversal>
119  : Category, Traversal
120 {};
121 
122 // Computes an iterator_category tag whose traversal is Traversal and
123 // which is appropriate for an iterator
124 template <class Traversal, class ValueParam, class Reference>
126 {
127  typedef typename iterator_facade_default_category<
128  Traversal,ValueParam,Reference
129  >::type category;
130 
131  typedef typename bolt::cl::detail::if_<
132  std::is_same<
133  Traversal
135  >
136  , category
138  >::type type;
139 };
140 
141 //
142 // Compute an iterator_category for iterator_facade
143 //
144 template <class CategoryOrTraversal, class ValueParam, class Reference>
146  : bolt::cl::detail::eval_if<
147  is_iterator_category<CategoryOrTraversal>
148  , bolt::cl::detail::identity_<CategoryOrTraversal> // old-style categories are fine as-is
149  , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
150  >
151 {
152 };
153 
154 }}} // namespace bolt::cl::detail
155 
156 
157 #endif // BOLT_FACADE_ITERATOR_CATEGORY_H