/* * Copyright 2008-2018 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. */ /*! \file tuple.h * \brief A type encapsulating a heterogeneous collection of elements. */ /* * Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying NOTICE file for the complete license) * * For more information, see http://www.boost.org */ #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 THRUST_NAMESPACE_BEGIN // define null_type for backwards compatability struct null_type {}; _CCCL_HOST_DEVICE inline bool operator==(const null_type&, const null_type&) { return true; } _CCCL_HOST_DEVICE inline bool operator>=(const null_type&, const null_type&) { return true; } _CCCL_HOST_DEVICE inline bool operator<=(const null_type&, const null_type&) { return true; } _CCCL_HOST_DEVICE inline bool operator!=(const null_type&, const null_type&) { return false; } _CCCL_HOST_DEVICE inline bool operator<(const null_type&, const null_type&) { return false; } _CCCL_HOST_DEVICE inline bool operator>(const null_type&, const null_type&) { return false; } /*! \addtogroup utility * \{ */ /*! \addtogroup tuple * \{ */ /*! This metafunction returns the type of a * \p tuple's Nth element. * * \tparam N This parameter selects the element of interest. * \tparam T A \c tuple type of interest. * * \see pair * \see tuple */ template using tuple_element = _CUDA_VSTD::tuple_element; /*! This metafunction returns the number of elements * of a \p tuple type of interest. * * \tparam T A \c tuple type of interest. * * \see pair * \see tuple */ template using tuple_size = _CUDA_VSTD::tuple_size; template struct __is_tuple_of_iterator_references : _CUDA_VSTD::false_type {}; /*! \brief \p tuple is a class template that can be instantiated with up to ten * arguments. Each template argument specifies the type of element in the \p * tuple. Consequently, tuples are heterogeneous, fixed-size collections of * values. An instantiation of \p tuple with two arguments is similar to an * instantiation of \p pair with the same two arguments. Individual elements * of a \p tuple may be accessed with the \p get function. * * \tparam TN The type of the N \c tuple element. Thrust's \p tuple * type currently supports up to ten elements. * * The following code snippet demonstrates how to create a new \p tuple object * and inspect and modify the value of its elements. * * \code * #include * #include * * int main() { * // Create a tuple containing an `int`, a `float`, and a string. * thrust::tuple t(13, 0.1f, "thrust"); * * // Individual members are accessed with the free function `get`. * std::cout << "The first element's value is " << thrust::get<0>(t) << std::endl; * * // ... or the member function `get`. * std::cout << "The second element's value is " << t.get<1>() << std::endl; * * // We can also modify elements with the same function. * thrust::get<0>(t) += 10; * } * \endcode * * \see pair * \see get * \see make_tuple * \see tuple_element * \see tuple_size * \see tie */ template struct tuple : public _CUDA_VSTD::tuple { using super_t = _CUDA_VSTD::tuple; using super_t::super_t; tuple() = default; template ::value, int> = 0, _CUDA_VSTD::__enable_if_t<(tuple_size<_TupleOfIteratorReferences>::value == sizeof...(Ts)), int> = 0> _CCCL_HOST_DEVICE tuple(_TupleOfIteratorReferences&& tup) : tuple(_CUDA_VSTD::forward<_TupleOfIteratorReferences>(tup).template __to_tuple( _CUDA_VSTD::__make_tuple_indices_t())) {} _CCCL_EXEC_CHECK_DISABLE template ::value, int> = 0> _CCCL_HOST_DEVICE tuple& operator=(TupleLike&& other) { super_t::operator=(_CUDA_VSTD::forward(other)); return *this; } #if defined(_CCCL_COMPILER_MSVC_2017) // MSVC2017 needs some help to convert tuples template , tuple>::value, int> = 0, _CUDA_VSTD::__enable_if_t<_CUDA_VSTD::__tuple_convertible<_CUDA_VSTD::tuple, super_t>::value, int> = 0> _CCCL_HOST_DEVICE constexpr operator tuple() { return __to_tuple(typename _CUDA_VSTD::__make_tuple_indices::type{}); } template _CCCL_HOST_DEVICE constexpr tuple __to_tuple(_CUDA_VSTD::__tuple_indices) const { return tuple{_CUDA_VSTD::get(*this)...}; } #endif // _CCCL_COMPILER_MSVC_2017 }; #if _CCCL_STD_VER >= 2017 template _CCCL_HOST_DEVICE tuple(Ts...) -> tuple; template struct pair; template _CCCL_HOST_DEVICE tuple(pair) -> tuple; #endif // _CCCL_STD_VER >= 2017 template inline _CCCL_HOST_DEVICE _CUDA_VSTD::__enable_if_t<_CUDA_VSTD::__all<_CUDA_VSTD::__is_swappable::value...>::value, void> swap(tuple& __x, tuple& __y) noexcept((_CUDA_VSTD::__all<_CUDA_VSTD::__is_nothrow_swappable::value...>::value)) { __x.swap(__y); } template inline _CCCL_HOST_DEVICE tuple::type...> make_tuple(Ts&&... __t) { return tuple::type...>(_CUDA_VSTD::forward(__t)...); } template inline _CCCL_HOST_DEVICE tuple tie(Ts&... ts) noexcept { return tuple(ts...); } using _CUDA_VSTD::get; /*! \endcond */ /*! \} // tuple */ /*! \} // utility */ THRUST_NAMESPACE_END _LIBCUDACXX_BEGIN_NAMESPACE_STD template struct tuple_size> : tuple_size> {}; template struct tuple_element> : tuple_element> {}; template struct __tuple_like_ext> : true_type {}; template <> struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size< tuple> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; template struct tuple_size> : tuple_size> {}; _LIBCUDACXX_END_NAMESPACE_STD // This is a workaround for the fact that structured bindings require that the specializations of // `tuple_size` and `tuple_element` reside in namespace std (https://eel.is/c++draft/dcl.struct.bind#4). // See https://github.com/NVIDIA/libcudacxx/issues/316 for a short discussion #if _CCCL_STD_VER >= 2017 namespace std { template struct tuple_size> : tuple_size> {}; template struct tuple_element> : tuple_element> {}; } // namespace std #endif // _CCCL_STD_VER >= 2017