thrust/zip_function.h
File members: thrust/zip_function.h
#pragma once
#include <thrust/detail/config.h>
#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 <thrust/detail/modern_gcc_required.h>
#if !defined(THRUST_LEGACY_GCC)
# include <thrust/detail/type_deduction.h>
# include <thrust/tuple.h>
# include <thrust/type_traits/integer_sequence.h>
# include <cuda/functional>
THRUST_NAMESPACE_BEGIN
namespace detail
{
namespace zip_detail
{
// Add workaround for decltype(auto) on C++11-only compilers:
# if _CCCL_STD_VER >= 2014
_CCCL_EXEC_CHECK_DISABLE
template <typename Function, typename Tuple, std::size_t... Is>
_CCCL_HOST_DEVICE decltype(auto) apply_impl(Function&& func, Tuple&& args, index_sequence<Is...>)
{
return func(thrust::get<Is>(THRUST_FWD(args))...);
}
template <typename Function, typename Tuple>
_CCCL_HOST_DEVICE decltype(auto) apply(Function&& func, Tuple&& args)
{
constexpr auto tuple_size = thrust::tuple_size<typename std::decay<Tuple>::type>::value;
return apply_impl(THRUST_FWD(func), THRUST_FWD(args), make_index_sequence<tuple_size>{});
}
# else // _CCCL_STD_VER
_CCCL_EXEC_CHECK_DISABLE
template <typename Function, typename Tuple, std::size_t... Is>
_CCCL_HOST_DEVICE auto apply_impl(Function&& func, Tuple&& args, index_sequence<Is...>)
THRUST_DECLTYPE_RETURNS(func(thrust::get<Is>(THRUST_FWD(args))...))
template <typename Function, typename Tuple>
_CCCL_HOST_DEVICE auto apply(Function&& func, Tuple&& args) THRUST_DECLTYPE_RETURNS(apply_impl(
THRUST_FWD(func),
THRUST_FWD(args),
make_index_sequence<thrust::tuple_size<typename std::decay<Tuple>::type>::value>{}))
# endif // _CCCL_STD_VER
} // namespace zip_detail
} // namespace detail
template <typename Function>
class zip_function
{
public:
zip_function() = default;
_CCCL_HOST_DEVICE zip_function(Function func)
: func(std::move(func))
{}
// Add workaround for decltype(auto) on C++11-only compilers:
# if _CCCL_STD_VER >= 2014
template <typename Tuple>
_CCCL_HOST_DEVICE decltype(auto) operator()(Tuple&& args) const
{
return detail::zip_detail::apply(func, THRUST_FWD(args));
}
# else // _CCCL_STD_VER
// Can't just use THRUST_DECLTYPE_RETURNS here since we need to use
// std::declval for the signature components:
template <typename Tuple>
_CCCL_HOST_DEVICE auto operator()(Tuple&& args) const
noexcept(noexcept(detail::zip_detail::apply(std::declval<Function>(), THRUST_FWD(args))))
-> decltype(detail::zip_detail::apply(std::declval<Function>(), THRUST_FWD(args)))
{
return detail::zip_detail::apply(func, THRUST_FWD(args));
}
# endif // _CCCL_STD_VER
_CCCL_HOST_DEVICE Function& underlying_function() const
{
return func;
}
private:
mutable Function func;
};
template <typename Function>
_CCCL_HOST_DEVICE zip_function<typename std::decay<Function>::type> make_zip_function(Function&& fun)
{
using func_t = typename std::decay<Function>::type;
return zip_function<func_t>(THRUST_FWD(fun));
}
THRUST_NAMESPACE_END
_LIBCUDACXX_BEGIN_NAMESPACE_CUDA
template <typename F>
struct proclaims_copyable_arguments<THRUST_NS_QUALIFIER::zip_function<F>> : proclaims_copyable_arguments<F>
{};
_LIBCUDACXX_END_NAMESPACE_CUDA
#endif