/* * Copyright 2008-2013 NVIDIA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) # pragma GCC system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) # pragma clang system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) # pragma system_header #endif // no system header #include #include #include #include #if !_THRUST_HAS_DEVICE_SYSTEM_STD # include #endif // the order of declarations and definitions in this file is totally goofy // this header defines raw_reference_cast, which has a few overloads towards the bottom of the file // raw_reference_cast depends on metafunctions such as is_unwrappable and raw_reference // we need to be sure that these metafunctions are completely defined (including specializations) before they are // instantiated by raw_reference_cast THRUST_NAMESPACE_BEGIN namespace detail { template class tuple_of_iterator_references; __THRUST_DEFINE_HAS_NESTED_TYPE(is_wrapped_reference, wrapped_reference_hint) // wrapped reference-like things which aren't strictly wrapped references // (e.g. tuples of wrapped references) are considered unwrappable template struct is_unwrappable : is_wrapped_reference {}; // specialize is_unwrappable // a tuple is_unwrappable if any of its elements is_unwrappable template struct is_unwrappable> : _THRUST_STD::disjunction...> {}; // specialize is_unwrappable // a tuple_of_iterator_references is_unwrappable if any of its elements is_unwrappable template struct is_unwrappable> : _THRUST_STD::disjunction...> {}; template struct enable_if_unwrappable : _THRUST_STD::enable_if::value, Result> {}; namespace raw_reference_detail { template struct raw_reference_impl : _THRUST_STD::add_lvalue_reference {}; template struct raw_reference_impl>::value>> { using type = _THRUST_STD::add_lvalue_reference_t::type>; }; } // namespace raw_reference_detail template struct raw_reference : raw_reference_detail::raw_reference_impl {}; namespace raw_reference_detail { // unlike raw_reference, // raw_reference_tuple_helper needs to return a value // when it encounters one, rather than a reference // upon encountering tuple, recurse // // we want the following behavior: // 1. T -> T // 2. T& -> T& // 3. null_type -> null_type // 4. reference -> T& // 5. tuple_of_iterator_references -> tuple_of_iterator_references::type> // wrapped references are unwrapped using raw_reference, otherwise, return T template struct raw_reference_tuple_helper : eval_if>::value, raw_reference, identity_> {}; // recurse on tuples template struct raw_reference_tuple_helper> { using type = thrust::tuple::type...>; }; template struct raw_reference_tuple_helper> { using type = thrust::detail::tuple_of_iterator_references::type...>; }; } // namespace raw_reference_detail // a couple of specializations of raw_reference for tuples follow // if a tuple "tuple_type" is_unwrappable, // then the raw_reference of tuple_type is a tuple of its members' raw_references // else the raw_reference of tuple_type is tuple_type & template struct raw_reference> { private: using tuple_type = thrust::tuple; public: using type = typename eval_if::value, raw_reference_detail::raw_reference_tuple_helper, _THRUST_STD::add_lvalue_reference>::type; }; template struct raw_reference> { private: using tuple_type = detail::tuple_of_iterator_references; public: using type = typename raw_reference_detail::raw_reference_tuple_helper::type; }; } // namespace detail // provide declarations of raw_reference_cast's overloads for raw_reference_caster below template THRUST_HOST_DEVICE typename detail::raw_reference::type raw_reference_cast(T& ref); template THRUST_HOST_DEVICE typename detail::raw_reference::type raw_reference_cast(const T& ref); template THRUST_HOST_DEVICE typename detail::enable_if_unwrappable< thrust::detail::tuple_of_iterator_references, typename detail::raw_reference>::type>::type raw_reference_cast(thrust::detail::tuple_of_iterator_references t); namespace detail { struct raw_reference_caster { template THRUST_HOST_DEVICE typename detail::raw_reference::type operator()(T& ref) { return thrust::raw_reference_cast(ref); } template THRUST_HOST_DEVICE typename detail::raw_reference::type operator()(const T& ref) { return thrust::raw_reference_cast(ref); } template THRUST_HOST_DEVICE typename detail::raw_reference>::type operator()(thrust::detail::tuple_of_iterator_references t, _THRUST_STD::enable_if_t>::value>* = 0) { return thrust::raw_reference_cast(t); } }; // end raw_reference_caster } // namespace detail template THRUST_HOST_DEVICE typename detail::raw_reference::type raw_reference_cast(T& ref) { return *thrust::raw_pointer_cast(&ref); } // end raw_reference_cast template THRUST_HOST_DEVICE typename detail::raw_reference::type raw_reference_cast(const T& ref) { return *thrust::raw_pointer_cast(&ref); } // end raw_reference_cast template THRUST_HOST_DEVICE typename detail::enable_if_unwrappable< thrust::detail::tuple_of_iterator_references, typename detail::raw_reference>::type>::type raw_reference_cast(thrust::detail::tuple_of_iterator_references t) { thrust::detail::raw_reference_caster f; // note that we pass raw_reference_tuple_helper, not raw_reference as the unary metafunction // the different way that raw_reference_tuple_helper unwraps tuples is important return thrust::detail::tuple_host_device_transform(t, f); } // end raw_reference_cast THRUST_NAMESPACE_END