2 * Copyright 2008-2013 NVIDIA Corporation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <thrust/detail/config.h>
20 #include <thrust/detail/raw_reference_cast.h>
21 #include <thrust/detail/type_traits.h>
22 #include <thrust/detail/tuple_transform.h>
29 // specialize is_unwrappable
30 // a tuple is_unwrappable if any of its elements is_unwrappable
32 typename T0, typename T1, typename T2,
33 typename T3, typename T4, typename T5,
34 typename T6, typename T7, typename T8,
37 struct is_unwrappable<
38 thrust::tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
55 // specialize is_unwrappable
56 // a tuple_of_iterator_references is_unwrappable if any of its elements is_unwrappable
58 typename T0, typename T1, typename T2,
59 typename T3, typename T4, typename T5,
60 typename T6, typename T7, typename T8,
63 struct is_unwrappable<
64 thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
81 namespace raw_reference_detail
84 // unlike raw_reference,
85 // raw_reference_tuple_helper needs to return a value
86 // when it encounters one, rather than a reference
87 // upon encountering tuple, recurse
89 // we want the following behavior:
92 // 3. null_type -> null_type
93 // 4. reference<T> -> T&
94 // 5. tuple_of_iterator_references<T> -> tuple_of_iterator_references<raw_reference_tuple_helper<T>::type>
97 // wrapped references are unwrapped using raw_reference, otherwise, return T
99 struct raw_reference_tuple_helper
102 typename remove_cv<T>::type
112 typename T0, typename T1, typename T2,
113 typename T3, typename T4, typename T5,
114 typename T6, typename T7, typename T8,
117 struct raw_reference_tuple_helper<
118 thrust::tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
121 typedef thrust::tuple<
122 typename raw_reference_tuple_helper<T0>::type,
123 typename raw_reference_tuple_helper<T1>::type,
124 typename raw_reference_tuple_helper<T2>::type,
125 typename raw_reference_tuple_helper<T3>::type,
126 typename raw_reference_tuple_helper<T4>::type,
127 typename raw_reference_tuple_helper<T5>::type,
128 typename raw_reference_tuple_helper<T6>::type,
129 typename raw_reference_tuple_helper<T7>::type,
130 typename raw_reference_tuple_helper<T8>::type,
131 typename raw_reference_tuple_helper<T9>::type
137 typename T0, typename T1, typename T2,
138 typename T3, typename T4, typename T5,
139 typename T6, typename T7, typename T8,
142 struct raw_reference_tuple_helper<
143 thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
146 typedef thrust::detail::tuple_of_iterator_references<
147 typename raw_reference_tuple_helper<T0>::type,
148 typename raw_reference_tuple_helper<T1>::type,
149 typename raw_reference_tuple_helper<T2>::type,
150 typename raw_reference_tuple_helper<T3>::type,
151 typename raw_reference_tuple_helper<T4>::type,
152 typename raw_reference_tuple_helper<T5>::type,
153 typename raw_reference_tuple_helper<T6>::type,
154 typename raw_reference_tuple_helper<T7>::type,
155 typename raw_reference_tuple_helper<T8>::type,
156 typename raw_reference_tuple_helper<T9>::type
161 } // end raw_reference_detail
164 // if a tuple "tuple_type" is_unwrappable,
165 // then the raw_reference of tuple_type is a tuple of its members' raw_references
166 // else the raw_reference of tuple_type is tuple_type &
168 typename T0, typename T1, typename T2,
169 typename T3, typename T4, typename T5,
170 typename T6, typename T7, typename T8,
173 struct raw_reference<
174 thrust::tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
178 typedef thrust::tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> tuple_type;
181 typedef typename eval_if<
182 is_unwrappable<tuple_type>::value,
183 raw_reference_detail::raw_reference_tuple_helper<tuple_type>,
184 add_reference<tuple_type>
190 typename T0, typename T1, typename T2,
191 typename T3, typename T4, typename T5,
192 typename T6, typename T7, typename T8,
195 struct raw_reference<
196 thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
200 typedef detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> tuple_type;
203 typedef typename raw_reference_detail::raw_reference_tuple_helper<tuple_type>::type type;
205 // XXX figure out why is_unwrappable seems to be broken for tuple_of_iterator_references
206 //typedef typename eval_if<
207 // is_unwrappable<tuple_type>::value,
208 // raw_reference_detail::raw_reference_tuple_helper<tuple_type>,
209 // add_reference<tuple_type>
214 struct raw_reference_caster
218 typename detail::raw_reference<T>::type operator()(T &ref)
220 return thrust::raw_reference_cast(ref);
225 typename detail::raw_reference<const T>::type operator()(const T &ref)
227 return thrust::raw_reference_cast(ref);
231 typename T0, typename T1, typename T2,
232 typename T3, typename T4, typename T5,
233 typename T6, typename T7, typename T8,
237 typename detail::raw_reference<
238 thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
240 operator()(thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> t,
242 is_unwrappable<thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> >::value
245 return thrust::raw_reference_cast(t);
247 }; // end raw_reference_caster
254 typename T0, typename T1, typename T2,
255 typename T3, typename T4, typename T5,
256 typename T6, typename T7, typename T8,
260 typename detail::enable_if_unwrappable<
261 thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>,
262 typename detail::raw_reference<
263 thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
266 raw_reference_cast(thrust::detail::tuple_of_iterator_references<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> t)
268 thrust::detail::raw_reference_caster f;
270 // note that we pass raw_reference_tuple_helper, not raw_reference as the unary metafunction
271 // the subtle difference is important
272 return thrust::detail::tuple_host_device_transform<detail::raw_reference_detail::raw_reference_tuple_helper>(t, f);
273 } // end raw_reference_cast